fetch_paper_details
Retrieve comprehensive details for a specific academic paper, including metadata and abstracts, by providing its unique identifier and preferred database source (Crossref or Semantic Scholar).
Instructions
Get detailed information about a specific paper.
Args:
paper_id: Paper identifier (DOI for Crossref, paper ID for Semantic Scholar)
source: Source database ("semantic_scholar" or "crossref")
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| paper_id | Yes | ||
| source | No | semantic_scholar |
Implementation Reference
- server.py:134-158 (handler)The main handler function for the 'fetch_paper_details' tool. It constructs the appropriate API URL based on the source, fetches the data using make_api_request, handles Crossref response structure, and formats the output using format_paper_data. Registered via @mcp.tool() decorator.@mcp.tool() async def fetch_paper_details(paper_id: str, source: str = "semantic_scholar") -> str: """Get detailed information about a specific paper. Args: paper_id: Paper identifier (DOI for Crossref, paper ID for Semantic Scholar) source: Source database ("semantic_scholar" or "crossref") """ if source == "semantic_scholar": url = f"{SEMANTIC_SCHOLAR_API}/paper/{paper_id}" elif source == "crossref": url = f"{CROSSREF_API}/{paper_id}" else: return "Unsupported source. Please use 'semantic_scholar' or 'crossref'." data = await make_api_request(url) if not data: return f"Unable to fetch paper details from {source}." if source == "crossref": data = data.get('message', {}) return format_paper_data(data, source)
- server.py:26-37 (helper)Helper function to make HTTP requests to the Semantic Scholar or Crossref APIs with error handling and timeout.async def make_api_request(url: str, headers: dict = None, params: dict = None) -> dict[str, Any] | None: """Make a request to the API with proper error handling.""" if headers is None: headers = { "User-Agent": USER_AGENT } async with httpx.AsyncClient() as client: try: response = await client.get(url, headers=headers, params=params, timeout=30.0) response.raise_for_status() return response.json() except Exception as e: return None
- server.py:38-86 (helper)Helper function that formats the raw API response data from either source into a consistent human-readable string format, handling fields like title, authors, year, DOI, and source-specific fields.def format_paper_data(data: dict, source: str) -> str: """Format paper data from different sources into a consistent string format.""" if not data: return "No paper data available" try: if source == "semantic_scholar": title = unicodedata.normalize('NFKD', str(data.get('title', 'No title available'))) authors = ', '.join([author.get('name', 'Unknown Author') for author in data.get('authors', [])]) year = data.get('year') or 'Year unknown' external_ids = data.get('externalIds', {}) or {} doi = external_ids.get('DOI', 'No DOI available') venue = data.get('venue') or 'Venue unknown' abstract = data.get('abstract') or 'No abstract available' tldr = (data.get('tldr') or {}).get('text', '') is_open = "Yes" if data.get('isOpenAccess') else "No" pdf_data = data.get('openAccessPdf', {}) or {} pdf_url = pdf_data.get('url', 'Not available') elif source == "crossref": title = (data.get('title') or ['No title available'])[0] authors = ', '.join([ f"{author.get('given', '')} {author.get('family', '')}".strip() or 'Unknown Author' for author in data.get('author', []) ]) year = (data.get('published-print', {}).get('date-parts', [['']])[0][0]) or 'Year unknown' doi = data.get('DOI') or 'No DOI available' result = [ f"Title: {title}", f"Authors: {authors}", f"Year: {year}", f"DOI: {doi}" ] if source == "semantic_scholar": result.extend([ f"Venue: {venue}", f"Open Access: {is_open}", f"PDF URL: {pdf_url}", f"Abstract: {abstract}" ]) if tldr: result.append(f"TL;DR: {tldr}") return "\n".join(result) + "\t\t\n" except Exception as e: return f"Error formatting paper data: {str(e)}"
- server.py:134-134 (registration)The @mcp.tool() decorator registers the fetch_paper_details function as an MCP tool.@mcp.tool()