Skip to main content
Glama
by fegizii

search_papers

Search academic papers using Semantic Scholar by specifying query, filters like open access PDFs, citation count, year, venue, and fields for tailored results. Retrieve formatted outputs for research purposes.

Instructions

Search for academic papers using Semantic Scholar. Args: query: Search query string limit: Maximum number of results (default: 10, max: 100) offset: Number of results to skip (default: 0) fields: Comma-separated list of fields to return publication_types: Filter by publication types open_access_pdf: Filter for papers with open access PDFs min_citation_count: Minimum citation count year: Publication year or year range (e.g., "2020-2023") venue: Publication venue Returns: Formatted search results

Input Schema

NameRequiredDescriptionDefault
fieldsNo
limitNo
min_citation_countNo
offsetNo
open_access_pdfNo
publication_typesNo
queryYes
venueNo
yearNo

Input Schema (JSON Schema)

{ "properties": { "fields": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Fields" }, "limit": { "default": 10, "title": "Limit", "type": "integer" }, "min_citation_count": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "title": "Min Citation Count" }, "offset": { "default": 0, "title": "Offset", "type": "integer" }, "open_access_pdf": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "title": "Open Access Pdf" }, "publication_types": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Publication Types" }, "query": { "title": "Query", "type": "string" }, "venue": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Venue" }, "year": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Year" } }, "required": [ "query" ], "title": "search_papersArguments", "type": "object" }

Implementation Reference

  • The core handler function for the 'search_papers' MCP tool. It is decorated with @mcp.tool() for automatic registration, defines the input schema via typed parameters and docstring, queries the Semantic Scholar API's paper/search endpoint, processes the response, formats results using helper functions, and returns a formatted string of paper information.
    @mcp.tool() async def search_papers( query: str, limit: int = 10, offset: int = 0, fields: Optional[str] = None, publication_types: Optional[str] = None, open_access_pdf: Optional[bool] = None, min_citation_count: Optional[int] = None, year: Optional[str] = None, venue: Optional[str] = None, ) -> str: """ Search for academic papers using Semantic Scholar. Args: query: Search query string limit: Maximum number of results (default: 10, max: 100) offset: Number of results to skip (default: 0) fields: Comma-separated list of fields to return publication_types: Filter by publication types open_access_pdf: Filter for papers with open access PDFs min_citation_count: Minimum citation count year: Publication year or year range (e.g., "2020-2023") venue: Publication venue Returns: Formatted search results """ params = {"query": query, "limit": min(limit, 100), "offset": offset} if fields: params["fields"] = fields else: params["fields"] = "paperId,title,authors,year,venue,citationCount,abstract" if publication_types: params["publicationTypes"] = publication_types if open_access_pdf is not None: params["openAccessPdf"] = str(open_access_pdf).lower() if min_citation_count is not None: params["minCitationCount"] = min_citation_count if year: params["year"] = year if venue: params["venue"] = venue result = await make_api_request("paper/search", params) if result is None: return "Error: Failed to fetch results" if "error" in result: return f"Error: {result['error']}" papers = result.get("data", []) total = result.get("total", 0) if not papers: return "No papers found matching your query." formatted_papers = [] for i, paper in enumerate(papers, 1): formatted_papers.append(f"{i}. {format_paper(paper)}") result_text = f"Found {total} total papers (showing {len(papers)}):\n\n" result_text += "\n\n".join(formatted_papers) return result_text
  • Helper function used by search_papers to format individual paper details into a readable string including title, authors, year, venue, citations, and paper ID.
    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}"
  • Shared helper function used by search_papers (and other tools) to make authenticated HTTP requests to the Semantic Scholar API, handling errors like rate limits and API keys.
    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