Skip to main content
Glama
kujenga
by kujenga

zotero_item_metadata

Retrieve detailed metadata for a specific Zotero library item using its unique item key.

Instructions

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

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
item_keyYes

Implementation Reference

  • The core handler function decorated with @mcp.tool(name="zotero_item_metadata"). It fetches the Zotero item using the provided key, formats it using format_item helper, and handles errors.
    @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)}"
  • Supporting helper function that formats the raw Zotero item data into a human-readable Markdown string, handling notes specially and including metadata like creators, tags, abstract, etc.
    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)
  • The @mcp.tool decorator registers the get_item_metadata function as the 'zotero_item_metadata' tool with its description and inferred schema from function signature.
    @mcp.tool(
        name="zotero_item_metadata",
        description="Get metadata information about a specific Zotero item, given the item key.",
    )

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