Skip to main content
Glama
fegizii

Semantic Scholar MCP Server

by fegizii

get_paper

Retrieve detailed academic paper information using Semantic Scholar, ArXiv, or DOI identifiers. Specify fields to get citations, references, authors, and metadata.

Instructions

Get detailed information about a specific paper.

Args:
    paper_id: Paper ID (can be Semantic Scholar ID, DOI, ArXiv ID, etc.)
    fields: Comma-separated list of fields to return

Returns:
    Detailed paper information

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paper_idYes
fieldsNo

Implementation Reference

  • Core handler function for the 'get_paper' tool. Decorated with @mcp.tool() for automatic registration and schema inference. Fetches paper details from Semantic Scholar API endpoint /paper/{paper_id}, handles errors, extracts key fields, and formats a detailed text response including title, authors, abstract, citations, references count, and PDF info.
    @mcp.tool()
    async def get_paper(paper_id: str, fields: Optional[str] = None) -> str:
        """
        Get detailed information about a specific paper.
    
        Args:
            paper_id: Paper ID (can be Semantic Scholar ID, DOI, ArXiv ID, etc.)
            fields: Comma-separated list of fields to return
    
        Returns:
            Detailed paper information
        """
        params = {}
        if fields:
            params["fields"] = fields
        else:
            params["fields"] = (
                "paperId,title,authors,year,venue,citationCount,abstract,references,citations,openAccessPdf"
            )
    
        # URL encode the paper ID to handle DOIs and other special characters
        encoded_id = quote(paper_id, safe="")
    
        result = await make_api_request(f"paper/{encoded_id}", params)
    
        if result is None:
            return "Error: Failed to fetch paper"
    
        if "error" in result:
            return f"Error: {result['error']}"
    
        paper = result
        title = paper.get("title", "Unknown Title")
        authors = paper.get("authors", [])
        author_names = [author.get("name", "Unknown") for author in authors]
    
        year = paper.get("year", "Unknown")
        venue = paper.get("venue", "Unknown")
        citation_count = paper.get("citationCount", 0)
        abstract = paper.get("abstract", "No abstract available")
    
        references = paper.get("references", [])
        citations = paper.get("citations", [])
    
        open_access = paper.get("openAccessPdf")
        pdf_url = open_access.get("url") if open_access else "No open access PDF"
    
        result_text = f"""Title: {title}
    Authors: {', '.join(author_names)}
    Year: {year}
    Venue: {venue}
    Citations: {citation_count}
    Paper ID: {paper.get('paperId', 'Unknown')}
    
    Abstract:
    {abstract}
    
    References: {len(references)}
    Cited by: {len(citations)}
    Open Access PDF: {pdf_url}"""
    
        return result_text
  • Key helper function used by get_paper to perform authenticated API requests to Semantic Scholar, with comprehensive error handling for rate limits, HTTP errors, and general exceptions.
    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