Skip to main content
Glama
openags

Paper Search MCP

by openags

search_papers

Search academic papers across multiple platforms simultaneously to find research publications. This tool aggregates results from sources like arXiv, PubMed, and Google Scholar in a single query.

Instructions

Unified top-level search across all configured academic platforms.

Args: query: Search query string. max_results_per_source: Max results to fetch from each selected source. sources: Comma-separated source names or 'all'. Available: arxiv,pubmed,biorxiv,medrxiv,google_scholar,iacr,semantic,crossref,openalex,pmc,core,europepmc,dblp,openaire,citeseerx,doaj,base,zenodo,hal,ssrn,unpaywall year: Optional year filter for Semantic Scholar only. Returns: Aggregated dictionary with per-source stats, errors, and deduplicated papers.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
max_results_per_sourceNo
sourcesNoall
yearNo

Implementation Reference

  • The 'search_papers' tool handler, which orchestrates searches across various academic platforms based on the user-provided 'sources' parameter.
    async def search_papers(
        query: str,
        max_results_per_source: int = 5,
        sources: str = "all",
        year: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Unified top-level search across all configured academic platforms.
    
        Args:
            query: Search query string.
            max_results_per_source: Max results to fetch from each selected source.
            sources: Comma-separated source names or 'all'.
                Available: arxiv,pubmed,biorxiv,medrxiv,google_scholar,iacr,semantic,crossref,openalex,pmc,core,europepmc,dblp,openaire,citeseerx,doaj,base,zenodo,hal,ssrn,unpaywall
            year: Optional year filter for Semantic Scholar only.
        Returns:
            Aggregated dictionary with per-source stats, errors, and deduplicated papers.
        """
        selected_sources = _parse_sources(sources)
    
        if not selected_sources:
            return {
                "query": query,
                "sources_requested": sources,
                "sources_used": [],
                "source_results": {},
                "errors": {"sources": "No valid sources selected."},
                "papers": [],
                "total": 0,
            }
    
        task_map = {}
        for source in selected_sources:
            if source == "arxiv":
                task_map[source] = search_arxiv(query, max_results_per_source)
            elif source == "pubmed":
                task_map[source] = search_pubmed(query, max_results_per_source)
            elif source == "biorxiv":
                task_map[source] = search_biorxiv(query, max_results_per_source)
            elif source == "medrxiv":
                task_map[source] = search_medrxiv(query, max_results_per_source)
            elif source == "google_scholar":
                task_map[source] = search_google_scholar(query, max_results_per_source)
            elif source == "iacr":
                task_map[source] = search_iacr(query, max_results_per_source, fetch_details=False)
            elif source == "semantic":
                task_map[source] = search_semantic(query, year=year, max_results=max_results_per_source)
            elif source == "crossref":
                task_map[source] = search_crossref(query, max_results=max_results_per_source)
            elif source == "openalex":
                task_map[source] = search_openalex(query, max_results_per_source)
            elif source == "pmc":
                task_map[source] = search_pmc(query, max_results_per_source)
            elif source == "core":
                task_map[source] = search_core(query, max_results_per_source)
            elif source == "europepmc":
                task_map[source] = search_europepmc(query, max_results_per_source)
            elif source == "dblp":
                task_map[source] = search_dblp(query, max_results_per_source)
            elif source == "openaire":
                task_map[source] = search_openaire(query, max_results_per_source)
            elif source == "citeseerx":
                task_map[source] = search_citeseerx(query, max_results_per_source)
            elif source == "doaj":
                task_map[source] = search_doaj(query, max_results_per_source)
            elif source == "base":
                task_map[source] = search_base(query, max_results_per_source)
            elif source == "zenodo":
                task_map[source] = search_zenodo(query, max_results_per_source)
            elif source == "hal":
                task_map[source] = search_hal(query, max_results_per_source)
            elif source == "ssrn":
                task_map[source] = search_ssrn(query, max_results_per_source)
            elif source == "unpaywall":
                task_map[source] = search_unpaywall(query, max_results_per_source)
            elif source == "ieee":
                if ieee_searcher is not None:
                    task_map[source] = async_search(ieee_searcher, query, max_results_per_source)
            elif source == "acm":
                if acm_searcher is not None:
                    task_map[source] = async_search(acm_searcher, query, max_results_per_source)
    
        source_names = list(task_map.keys())
        source_outputs = await asyncio.gather(*task_map.values(), return_exceptions=True)

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/openags/paper-search-mcp'

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