Skip to main content
Glama
fegizii

Semantic Scholar MCP Server

by fegizii

get_paper_citations

Retrieve academic papers that cite a specific publication to analyze research impact and track scholarly influence.

Instructions

Get papers that cite a specific paper.

Args:
    paper_id: Paper ID to get citations for
    limit: Maximum number of results (default: 10, max: 1000)
    offset: Number of results to skip (default: 0)
    fields: Comma-separated list of fields to return

Returns:
    List of citing papers

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paper_idYes
limitNo
offsetNo
fieldsNo

Implementation Reference

  • The main handler function for the 'get_paper_citations' tool. It is registered via @mcp.tool() decorator, defines input schema via type annotations and docstring, fetches citations using make_api_request, formats them with format_paper, and returns formatted string output.
    @mcp.tool()
    async def get_paper_citations(
        paper_id: str, limit: int = 10, offset: int = 0, fields: Optional[str] = None
    ) -> str:
        """
        Get papers that cite a specific paper.
    
        Args:
            paper_id: Paper ID to get citations for
            limit: Maximum number of results (default: 10, max: 1000)
            offset: Number of results to skip (default: 0)
            fields: Comma-separated list of fields to return
    
        Returns:
            List of citing papers
        """
        params: Dict[str, Any] = {"limit": min(limit, 1000), "offset": offset}
    
        if fields:
            params["fields"] = fields
        else:
            params["fields"] = "paperId,title,authors,year,venue,citationCount"
    
        encoded_id = quote(paper_id, safe="")
        result = await make_api_request(f"paper/{encoded_id}/citations", params)
    
        if result is None:
            return "Error: Failed to fetch citations"
    
        if "error" in result:
            return f"Error: {result['error']}"
    
        citations = result.get("data", [])
        total = result.get("total", 0)
    
        if not citations:
            return "No citations found for this paper."
    
        formatted_citations = []
        for i, citation in enumerate(citations, 1):
            citing_paper = citation.get("citingPaper", {})
            if citing_paper:
                formatted_citations.append(f"{i}. {format_paper(citing_paper)}")
    
        result_text = (
            f"Found {total} total citations (showing {len(formatted_citations)}):\n\n"
        )
        result_text += "\n\n".join(formatted_citations)
    
        return result_text
  • Helper function used to format individual paper details in the citations list output.
    def format_paper(paper: Dict[str, Any]) -> str:
        """Format a paper for display."""
        title = paper.get("title", "Unknown Title")
        authors = paper.get("authors", [])
        author_names = [author.get("name", "Unknown") for author in authors[:3]]
        author_str = ", ".join(author_names)
        if len(authors) > 3:
            author_str += f" (and {len(authors) - 3} others)"
    
        year = paper.get("year")
        year_str = f" ({year})" if year else ""
    
        venue = paper.get("venue", "")
        venue_str = f" - {venue}" if venue else ""
    
        citation_count = paper.get("citationCount", 0)
    
        paper_id = paper.get("paperId", "")
    
        return f"Title: {title}\nAuthors: {author_str}{year_str}{venue_str}\nCitations: {citation_count}\nPaper ID: {paper_id}"
  • Core helper function that makes HTTP requests to the Semantic Scholar API, handles errors and rate limits, used by get_paper_citations to fetch the citations data.
    async def make_api_request(
        endpoint: str, params: Optional[Dict[str, Any]] = None, method: str = "GET"
    ) -> Optional[Dict[str, Any]]:
        """Make a request to the Semantic Scholar API."""
        url = f"{BASE_URL}/{endpoint.lstrip('/')}"
    
        headers = {
            "Accept": "application/json",
            "User-Agent": f"semantic-scholar-mcp/{USER_AGENT_VERSION}",
        }
    
        if API_KEY:
            headers["x-api-key"] = API_KEY
    
        try:
            async with httpx.AsyncClient(timeout=API_TIMEOUT) as client:
                if method == "GET":
                    response = await client.get(url, headers=headers, params=params)
                elif method == "POST":
                    response = await client.post(url, headers=headers, json=params)
                else:
                    raise ValueError(f"Unsupported HTTP method: {method}")
    
                response.raise_for_status()
                return response.json()
    
        except httpx.HTTPStatusError as e:
            if e.response.status_code == 403:
                if not API_KEY:
                    return {
                        "error": "Rate limit exceeded. The shared public rate limit (1000 req/sec) may be exceeded. Get a free API key from https://www.semanticscholar.org/product/api for dedicated limits."
                    }
                else:
                    return {
                        "error": f"API key may be invalid or rate limit exceeded: {str(e)}"
                    }
            elif e.response.status_code == 429:
                return {
                    "error": "Rate limit exceeded. Please wait a moment and try again, or get an API key for dedicated higher limits."
                }
            else:
                return {"error": f"HTTP error: {str(e)}"}
        except httpx.HTTPError as e:
            return {"error": f"HTTP error: {str(e)}"}
        except Exception as e:
            return {"error": f"Request failed: {str(e)}"}

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/fegizii/SemanticScholarMCP'

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