Skip to main content
Glama

zotero_item_metadata

Retrieve detailed metadata for a specific Zotero library item using its unique item key, enabling efficient access to bibliographic information within the Zotero MCP Server.

Instructions

Get metadata information about a specific Zotero item, given the item key.

Input Schema

NameRequiredDescriptionDefault
item_keyYes

Input Schema (JSON Schema)

{ "properties": { "item_key": { "title": "Item Key", "type": "string" } }, "required": [ "item_key" ], "title": "get_item_metadataArguments", "type": "object" }

Implementation Reference

  • The handler function for the 'zotero_item_metadata' tool. It retrieves the Zotero item using the client and formats its metadata using the `format_item` helper.
    @mcp.tool( name="zotero_item_metadata", description="Get metadata information about a specific Zotero item, given the item key.", ) def get_item_metadata(item_key: str) -> str: """Get metadata information about a specific Zotero item""" zot = get_zotero_client() try: item: Any = zot.item(item_key) if not item: return f"No item found with key: {item_key}" return format_item(item) except Exception as e: return f"Error retrieving item metadata: {str(e)}"
  • Helper function `format_item` that formats a Zotero item's metadata into a human-readable Markdown string optimized for LLMs, used by the zotero_item_metadata tool.
    def format_item(item: dict[str, Any]) -> str: """Format a Zotero item's metadata as a readable string optimized for LLM consumption""" data = item["data"] item_key = item["key"] item_type = data.get("itemType", "unknown") # Special handling for notes if item_type == "note": # Get note content note_content = data.get("note", "") # Strip HTML tags for cleaner text (simple approach) note_content = ( note_content.replace("<p>", "").replace("</p>", "\n").replace("<br>", "\n") ) note_content = note_content.replace("<strong>", "**").replace("</strong>", "**") note_content = note_content.replace("<em>", "*").replace("</em>", "*") # Format note with clear sections formatted = [ "## 📝 Note", f"Item Key: `{item_key}`", ] # Add parent item reference if available if parent_item := data.get("parentItem"): formatted.append(f"Parent Item: `{parent_item}`") # Add date if available if date := data.get("dateModified"): formatted.append(f"Last Modified: {date}") # Add tags with formatting for better visibility if tags := data.get("tags"): tag_list = [f"`{tag['tag']}`" for tag in tags] formatted.append(f"\n### Tags\n{', '.join(tag_list)}") # Add note content formatted.append(f"\n### Note Content\n{note_content}") return "\n".join(formatted) # Regular item handling (non-notes) # Basic metadata with key for easy reference formatted = [ f"## {data.get('title', 'Untitled')}", f"Item Key: `{item_key}`", f"Type: {item_type}", f"Date: {data.get('date', 'No date')}", ] # Creators with role differentiation creators_by_role = {} for creator in data.get("creators", []): role = creator.get("creatorType", "contributor") name = "" if "firstName" in creator and "lastName" in creator: name = f"{creator['lastName']}, {creator['firstName']}" elif "name" in creator: name = creator["name"] if name: if role not in creators_by_role: creators_by_role[role] = [] creators_by_role[role].append(name) for role, names in creators_by_role.items(): role_display = role.capitalize() + ("s" if len(names) > 1 else "") formatted.append(f"{role_display}: {'; '.join(names)}") # Publication details if publication := data.get("publicationTitle"): formatted.append(f"Publication: {publication}") if volume := data.get("volume"): volume_info = f"Volume: {volume}" if issue := data.get("issue"): volume_info += f", Issue: {issue}" if pages := data.get("pages"): volume_info += f", Pages: {pages}" formatted.append(volume_info) # Abstract with clear section header if abstract := data.get("abstractNote"): formatted.append(f"\n### Abstract\n{abstract}") # Tags with formatting for better visibility if tags := data.get("tags"): tag_list = [f"`{tag['tag']}`" for tag in tags] formatted.append(f"\n### Tags\n{', '.join(tag_list)}") # URLs, DOIs, and identifiers grouped together identifiers = [] if url := data.get("url"): identifiers.append(f"URL: {url}") if doi := data.get("DOI"): identifiers.append(f"DOI: {doi}") if isbn := data.get("ISBN"): identifiers.append(f"ISBN: {isbn}") if issn := data.get("ISSN"): identifiers.append(f"ISSN: {issn}") if identifiers: formatted.append("\n### Identifiers\n" + "\n".join(identifiers)) # Notes and attachments if notes := item.get("meta", {}).get("numChildren", 0): formatted.append( f"\n### Additional Information\nNumber of notes/attachments: {notes}" ) return "\n".join(formatted)
  • Helper function `get_zotero_client` that initializes and returns an authenticated Zotero client instance, used by the zotero_item_metadata tool.
    def get_zotero_client() -> zotero.Zotero: """Get authenticated Zotero client using environment variables""" library_id = os.getenv("ZOTERO_LIBRARY_ID") library_type = os.getenv("ZOTERO_LIBRARY_TYPE", "user") api_key = os.getenv("ZOTERO_API_KEY") or None local = os.getenv("ZOTERO_LOCAL", "").lower() in ["true", "yes", "1"] if local: if not library_id: # Indicates "current user" for the local API library_id = "0" elif not all([library_id, api_key]): raise ValueError( "Missing required environment variables. Please set ZOTERO_LIBRARY_ID and ZOTERO_API_KEY" ) return zotero.Zotero( library_id=library_id, library_type=library_type, api_key=api_key, local=local, )

Other Tools

Related Tools

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

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