Skip to main content
Glama

search_authors

Find academic authors by name using OpenAlex API, with options to sort by relevance or citations and filter by institution.

Instructions

Searches for authors using the OpenAlex API.

Args: query: The search name to look for the authors. sort_by: The sorting criteria ("relevance_score" or "cited_by_count"). institution_id: An optional institution id to filter search results. e.g., "https://openalex.org/I123456789" page: The page number of the results to retrieve (default: 1).

Returns: A JSON object containing a list of authors+ids, or an error message if the search fails.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
institution_idNo
pageNo
queryYes
sort_byNorelevance_score

Implementation Reference

  • The main execution logic for the 'search_authors' tool. This async function queries the OpenAlex API for authors based on a search query, optional institution filter, sorting, and pagination. It handles errors, parses results using Author models, and returns a paginated PageResult. Registered via @mcp.tool decorator.
    @mcp.tool async def search_authors( query: str, sort_by: Literal["relevance_score", "cited_by_count"] = "relevance_score", institution_id: Optional[str] = None, page: int = 1, ) -> PageResult: """ Searches for authors using the OpenAlex API. Args: query: The search name to look for the authors. sort_by: The sorting criteria ("relevance_score" or "cited_by_count"). institution_id: An optional institution id to filter search results. e.g., "https://openalex.org/I123456789" page: The page number of the results to retrieve (default: 1). Returns: A JSON object containing a list of authors+ids, or an error message if the search fails. """ query = sanitize_search_text(query) params = { "filter": f"default.search:\"{query}\"", "sort": f"{sort_by}:desc", "page": page, "per_page": 10, } if institution_id: params["filter"] += f",affiliations.institution.id:\"{institution_id}\"" # Fetches search results from the OpenAlex API async with RequestAPI("https://api.openalex.org", default_params={"mailto": OPENALEX_MAILTO}) as api: logger.info(f"Searching for authors using: query={query}, sort_by={sort_by}, page={page}, institution_id={institution_id}") try: result = await api.aget("/authors", params=params) # Returns a message for when the search results are empty if result is None or len(result.get("results", []) or []) == 0: error_message = "No authors found with the query." logger.info(error_message) raise ToolError(error_message) # Successfully returns the searched authors authors = Author.from_list(result.get("results", []) or []) success_message = f"Found {len(authors)} authors." logger.info(success_message) total_count = (result.get("meta", {}) or {}).get("count") if total_count and total_count > params["per_page"] * params["page"]: has_next = True else: has_next = None return PageResult( data=Author.list_to_json(authors), total_count=total_count, per_page=params["per_page"], page=params["page"], has_next=has_next ) except httpx.HTTPStatusError as e: error_message = f"Request failed with status: {e.response.status_code}" logger.error(error_message) raise ToolError(error_message) except httpx.RequestError as e: error_message = f"Network error: {str(e)}" logger.error(error_message) raise ToolError(error_message)
  • Output schema used by search_authors (and other search tools). Defines the structure of paginated results including data list, metadata.
    class PageResult(BaseModel): data: List[Union[Institution, Author, Work, dict]] = Field(default_factory=list) total_count: Optional[int] = None per_page: int page: int has_next: Optional[bool] = None
  • Pydantic model for Author used in search_authors results parsing and serialization.
    class Author(BaseModel): model_config = ConfigDict( frozen=False, # set True for immutability validate_assignment=True, # runtime type safety on attribute set str_strip_whitespace=True, # trims incoming strings ) name: str id: Optional[str] = None institutions: List[Institution] = Field(default_factory=list) @classmethod def from_json(cls, json_obj: Dict[str, Any]) -> "Author": # Get author name and id author_info = json_obj.get("author", {}) or {} author_id = author_info.get("id") or json_obj.get("id") author_name = author_info.get("display_name") or json_obj.get("display_name") or "" # Get institutions from affiliations author_institutions = Institution.from_list(json_obj.get("affiliations", []) or []) return cls(name=author_name, id=author_id, institutions=author_institutions) @classmethod def from_list(cls, json_list: List[dict]) -> List["Author"]: return [cls.from_json(item) for item in json_list] @staticmethod def list_to_json(authors: List["Author"]) -> List[dict]: return [author.model_dump(exclude_none=True) for author in authors] def __str__(self) -> str: return self.model_dump_json(exclude_none=True)
  • Utility function to sanitize the search query by removing commas and normalizing whitespace, used in search_authors.
    import re def sanitize_search_text(s: str) -> str: """Remove commas and collapse whitespace for API search terms for OpenAlex to work""" if not s: return s s = s.replace(",", " ") s = re.sub(r"\s+", " ", s).strip() return s

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/ErikNguyen20/ScholarScope-MCP'

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