Skip to main content
Glama

zotero_get_item_metadata

Retrieve comprehensive metadata for a specific Zotero item using its unique key, including optional abstract, to enhance research and content analysis.

Instructions

Get detailed metadata for a specific Zotero item by its key.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
include_abstractNo
item_keyYes

Implementation Reference

  • Main handler function decorated with @mcp.tool for registration. Fetches Zotero item by key, then calls helpers to format as markdown or BibTeX.
    name="zotero_get_item_metadata", description="Get detailed metadata for a specific Zotero item by its key." ) def get_item_metadata( item_key: str, include_abstract: bool = True, format: Literal["markdown", "bibtex"] = "markdown", *, ctx: Context ) -> str: """ Get detailed metadata for a Zotero item. Args: item_key: Zotero item key/ID include_abstract: Whether to include the abstract in the output (markdown format only) format: Output format - 'markdown' for detailed metadata or 'bibtex' for BibTeX citation ctx: MCP context Returns: Formatted item metadata (markdown or BibTeX) """ try: ctx.info(f"Fetching metadata for item {item_key} in {format} format") zot = get_zotero_client() item = zot.item(item_key) if not item: return f"No item found with key: {item_key}" if format == "bibtex": return generate_bibtex(item) else: return format_item_metadata(item, include_abstract) except Exception as e: ctx.error(f"Error fetching item metadata: {str(e)}") return f"Error fetching item metadata: {str(e)}"
  • Helper function that formats the Zotero item dictionary into detailed markdown metadata, used by the main handler.
    def format_item_metadata(item: Dict[str, Any], include_abstract: bool = True) -> str: """ Format a Zotero item's metadata as markdown. Args: item: A Zotero item dictionary. include_abstract: Whether to include the abstract in the output. Returns: Markdown-formatted metadata. """ data = item.get("data", {}) item_type = data.get("itemType", "unknown") # Basic information lines = [ f"# {data.get('title', 'Untitled')}", f"**Type:** {item_type}", f"**Item Key:** {data.get('key')}", ] # Date if date := data.get("date"): lines.append(f"**Date:** {date}") # Authors/Creators if creators := data.get("creators", []): lines.append(f"**Authors:** {format_creators(creators)}") # Publication details based on item type if item_type == "journalArticle": if journal := data.get("publicationTitle"): journal_info = f"**Journal:** {journal}" if volume := data.get("volume"): journal_info += f", Volume {volume}" if issue := data.get("issue"): journal_info += f", Issue {issue}" if pages := data.get("pages"): journal_info += f", Pages {pages}" lines.append(journal_info) elif item_type == "book": if publisher := data.get("publisher"): book_info = f"**Publisher:** {publisher}" if place := data.get("place"): book_info += f", {place}" lines.append(book_info) # DOI and URL if doi := data.get("DOI"): lines.append(f"**DOI:** {doi}") if url := data.get("url"): lines.append(f"**URL:** {url}") # Tags if tags := data.get("tags"): tag_list = [f"`{tag['tag']}`" for tag in tags] if tag_list: lines.append(f"**Tags:** {' '.join(tag_list)}") # Abstract if include_abstract and (abstract := data.get("abstractNote")): lines.extend(["", "## Abstract", abstract]) # Collections if collections := data.get("collections", []): if collections: lines.append(f"**Collections:** {len(collections)} collections") # Notes - this requires additional API calls, so we just indicate if there are notes if "meta" in item and item["meta"].get("numChildren", 0) > 0: lines.append(f"**Notes/Attachments:** {item['meta']['numChildren']}") return "\n\n".join(lines)
  • Helper function that generates BibTeX citation for the Zotero item, with fallback to basic generation if Better BibTeX unavailable. Called by main handler for bibtex format.
    def generate_bibtex(item: Dict[str, Any]) -> str: """ Generate BibTeX format for a Zotero item. Args: item: Zotero item data Returns: BibTeX formatted string """ data = item.get("data", {}) item_key = data.get("key") # Try Better BibTeX first try: from zotero_mcp.better_bibtex_client import ZoteroBetterBibTexAPI bibtex = ZoteroBetterBibTexAPI() if bibtex.is_zotero_running(): return bibtex.export_bibtex(item_key) except Exception: # Continue to fallback method if Better BibTeX fails pass # Fallback to basic BibTeX generation item_type = data.get("itemType", "misc") if item_type in ["attachment", "note"]: raise ValueError(f"Cannot export BibTeX for item type '{item_type}'") # Map Zotero item types to BibTeX types type_map = { "journalArticle": "article", "book": "book", "bookSection": "incollection", "conferencePaper": "inproceedings", "thesis": "phdthesis", "report": "techreport", "webpage": "misc", "manuscript": "unpublished" } # Create citation key creators = data.get("creators", []) author = "" if creators: first = creators[0] author = first.get("lastName", first.get("name", "").split()[-1] if first.get("name") else "").replace(" ", "") year = data.get("date", "")[:4] if data.get("date") else "nodate" cite_key = f"{author}{year}_{item_key}" # Build BibTeX entry bib_type = type_map.get(item_type, "misc") lines = [f"@{bib_type}{{{cite_key},"] # Add fields field_mappings = [ ("title", "title"), ("publicationTitle", "journal"), ("volume", "volume"), ("issue", "number"), ("pages", "pages"), ("publisher", "publisher"), ("DOI", "doi"), ("url", "url"), ("abstractNote", "abstract") ] for zotero_field, bibtex_field in field_mappings: if value := data.get(zotero_field): # Escape special characters value = value.replace("{", "\\{").replace("}", "\\}") lines.append(f' {bibtex_field} = {{{value}}},') # Add authors if creators: authors = [] for creator in creators: if creator.get("creatorType") == "author": if "lastName" in creator and "firstName" in creator: authors.append(f"{creator['lastName']}, {creator['firstName']}") elif "name" in creator: authors.append(creator["name"]) if authors: lines.append(f' author = {{{" and ".join(authors)}}},') # Add year if year != "nodate": lines.append(f' year = {{{year}}},') # Remove trailing comma from last field and close entry if lines[-1].endswith(','): lines[-1] = lines[-1][:-1] lines.append("}") return "\n".join(lines)
  • Utility function to create and return the pyzotero Zotero client instance, used by the handler to fetch items.
    def get_zotero_client() -> zotero.Zotero: """ Get authenticated Zotero client using environment variables. Returns: A configured Zotero client instance. Raises: ValueError: If required environment variables are missing. """ library_id = os.getenv("ZOTERO_LIBRARY_ID") library_type = os.getenv("ZOTERO_LIBRARY_TYPE", "user") api_key = os.getenv("ZOTERO_API_KEY") local = os.getenv("ZOTERO_LOCAL", "").lower() in ["true", "yes", "1"] # For local API, default to user ID 0 if not specified if local and not library_id: library_id = "0" # For remote API, we need both library_id and api_key if not local and not (library_id and api_key): raise ValueError( "Missing required environment variables. Please set ZOTERO_LIBRARY_ID and ZOTERO_API_KEY, " "or use ZOTERO_LOCAL=true for local Zotero instance." ) return zotero.Zotero( library_id=library_id, library_type=library_type, api_key=api_key, local=local, )

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/54yyyu/zotero-mcp'

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