Skip to main content
Glama

apaper_search_crossref_papers

Search academic papers from Crossref database using queries, filters by year, and sorts results to support research.

Instructions

Search academic papers from Crossref database

Args: query: Search query string (e.g., 'quantum computing', 'machine learning') max_results: Maximum number of papers to return (default: 10) year_min: Minimum publication year (optional) year_max: Maximum publication year (optional) sort_by: Sort order: relevance, published, indexed, updated (default: relevance)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
max_resultsNo
year_minNo
year_maxNo
sort_byNorelevance

Implementation Reference

  • MCP tool handler function 'search_crossref_papers' that implements the core logic for searching Crossref papers, formatting results, and handling errors. This is likely exposed as 'apaper_search_crossref_papers' via the proxy.
    @mcp.tool()
    def search_crossref_papers(
        query: str,
        max_results: int = 10,
        year_min: int | str | None = None,
        year_max: int | str | None = None,
        sort_by: str = "relevance",
    ) -> str:
        """
        Search academic papers from Crossref database
        
        Args:
            query: Search query string (e.g., 'quantum computing', 'machine learning')
            max_results: Maximum number of papers to return (default: 10)
            year_min: Minimum publication year (optional)
            year_max: Maximum publication year (optional)
            sort_by: Sort order: relevance, published, indexed, updated (default: relevance)
        """
        try:
            # Convert string parameters to integers if needed
            year_min_int = None
            year_max_int = None
            
            if year_min is not None:
                year_min_int = int(year_min)
            
            if year_max is not None:
                year_max_int = int(year_max)
            
            papers = crossref_searcher.search(
                query,
                max_results=max_results,
                year_min=year_min_int,
                year_max=year_max_int,
                sort_by=sort_by,
            )
    
            if not papers:
                year_filter_msg = ""
                if year_min or year_max:
                    year_range = f" ({year_min or 'earliest'}-{year_max or 'latest'})"
                    year_filter_msg = f" in year range{year_range}"
                return f"No papers found for query: {query}{year_filter_msg}"
    
            year_filter_msg = ""
            if year_min or year_max:
                year_range = f" ({year_min or 'earliest'}-{year_max or 'latest'})"
                year_filter_msg = f" in year range{year_range}"
    
            result_text = f"Found {len(papers)} Crossref papers for query '{query}'{year_filter_msg}:\n\n"
            for i, paper in enumerate(papers, 1):
                result_text += f"{i}. **{paper.title}**\n"
                result_text += f"   - Authors: {', '.join(paper.authors)}\n"
                if paper.doi:
                    result_text += f"   - DOI: {paper.doi}\n"
                if paper.citations > 0:
                    result_text += f"   - Citations: {paper.citations}\n"
                if paper.published_date and paper.published_date.year > 1900:
                    result_text += f"   - Year: {paper.published_date.year}\n"
                if paper.extra and paper.extra.get("journal"):
                    result_text += f"   - Journal: {paper.extra['journal']}\n"
                if paper.extra and paper.extra.get("volume"):
                    result_text += f"   - Volume: {paper.extra['volume']}\n"
                if paper.extra and paper.extra.get("pages"):
                    result_text += f"   - Pages: {paper.extra['pages']}\n"
                if paper.url:
                    result_text += f"   - URL: {paper.url}\n"
                if paper.abstract:
                    # Truncate abstract for readability
                    abstract_preview = (
                        paper.abstract[:300] + "..."
                        if len(paper.abstract) > 300
                        else paper.abstract
                    )
                    result_text += f"   - Abstract: {abstract_preview}\n"
                result_text += "\n"
    
            return result_text
        except ValueError as e:
            return f"Error: Invalid year format. Please provide valid integers for year_min and year_max."
        except Exception as e:
            return f"Error searching Crossref: {str(e)}"
  • Core search method in CrossrefSearcher class that queries the Crossref API, parses responses into Paper objects, and applies filters.
    def search(
        self,
        query: str,
        max_results: int = 10,
        year_min: Optional[int] = None,
        year_max: Optional[int] = None,
        sort_by: str = "relevance",
        **kwargs,
    ) -> list[Paper]:
        """
        Search for papers using Crossref API
    
        Args:
            query: Search query string
            max_results: Maximum number of results to return
            year_min: Minimum publication year
            year_max: Maximum publication year
            sort_by: Sort order (relevance, published, indexed, updated)
        """
        if not query.strip():
            return []
    
        try:
            params = {
                "query": query,
                "rows": min(max_results, 1000),  # Crossref max is 1000
                "sort": sort_by,
                "select": "DOI,title,author,abstract,published-print,published-online,created,URL,container-title,volume,issue,page,subject,is-referenced-by-count,type,publisher,ISSN,ISBN,link",
            }
    
            # Add year filters if specified
            filters = []
            if year_min:
                filters.append(f"from-pub-date:{year_min}")
            if year_max:
                filters.append(f"until-pub-date:{year_max}")
    
            if filters:
                params["filter"] = ",".join(filters)
    
            response = self.client.get(
                self.WORKS_ENDPOINT, params=params, headers=self._get_headers()
            )
            response.raise_for_status()
    
            data = response.json()
            works = data.get("message", {}).get("items", [])
    
            papers = []
            for work in works:
                paper = self._parse_work(work)
                if paper:
                    papers.append(paper)
    
            return papers[:max_results]
    
        except Exception as e:
            logger.error(f"Error searching Crossref: {e}")
            return []
  • Import and instantiation of CrossrefSearcher used by the handler.
    from apaper.platforms import (
        IACRSearcher,
        CryptoBibSearcher,
        CrossrefSearcher,
        GoogleScholarSearcher
    )
    from apaper.utils.pdf_reader import read_pdf
    
    # Initialize FastMCP server
    mcp = FastMCP("apaper")
    
    # Initialize searchers
    iacr_searcher = IACRSearcher()
    cryptobib_searcher = CryptoBibSearcher(cache_dir="./downloads")
    crossref_searcher = CrossrefSearcher()
    google_scholar_searcher = GoogleScholarSearcher()

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/isomoes/all-in-mcp'

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