Skip to main content
Glama
renyumeng1

mcp-scholar

paper_references

Generate a list of papers citing a specific publication by entering its ID. Customize results by count and sorting options such as relevance, citations, date, or title. Facilitates research tracking and citation analysis.

Instructions

获取引用指定论文的文献列表

Args:
    paper_id: 论文ID
    count: 返回结果数量,默认为5
    sort_by: 排序方式,可选值:
        - "relevance": 按相关性排序(默认)
        - "citations": 按引用量排序
        - "date": 按发表日期排序(新到旧)
        - "title": 按标题字母顺序排序

Returns:
    Dict: 引用论文列表

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
countNo
paper_idYes
sort_byNorelevance

Implementation Reference

  • MCP tool handler for the 'paper_references' tool. It calls the helper function get_paper_references and formats the response.
    @mcp.tool()
    async def paper_references(
        ctx: Context, paper_id: str, count: int = 5, sort_by: str = "relevance"
    ) -> Dict[str, Any]:
        """
        获取引用指定论文的文献列表
    
        Args:
            paper_id: 论文ID
            count: 返回结果数量,默认为5
            sort_by: 排序方式,可选值:
                - "relevance": 按相关性排序(默认)
                - "citations": 按引用量排序
                - "date": 按发表日期排序(新到旧)
                - "title": 按标题字母顺序排序
    
        Returns:
            Dict: 引用论文列表
        """
        try:
            # 移除进度显示
            logger.info(f"正在获取论文ID为 {paper_id} 的引用...")
            references = await get_paper_references(paper_id, count, sort_by=sort_by)
    
            refs = []
            for ref in references:
                refs.append(
                    {
                        "title": ref["title"],
                        "authors": ref["authors"],
                        "abstract": ref["abstract"],
                        "citations": ref["citations"],
                        "year": ref.get("year", "Unknown"),
                        "paper_id": ref.get("paper_id", None),
                        "url": ref.get("url", ""),  # 添加URL
                        "doi_url": ref.get("doi_url", ""),  # 添加DOI URL
                    }
                )
    
            return {
                "status": "success",
                "references": refs,
                "sort_by": sort_by,
            }
        except Exception as e:
            error_msg = f"获取论文引用失败: {str(e)}"
            # 移除错误通知
            logger.error(error_msg, exc_info=True)
            return {"status": "error", "message": "论文引用服务暂时不可用", "error": str(e)}
  • Helper function implementing the core logic to fetch citing papers from OpenAlex API using the paper_id, handling different ID formats, sorting, and extracting relevant fields including abstract conversion from inverted index.
    async def get_paper_references(
        paper_id: str, count: int = 5, sort_by: str = "relevance"
    ) -> List[Dict[str, Any]]:
        """
        通过OpenAlex API获取引用指定论文的文献
    
        Args:
            paper_id: 论文ID,可以是OpenAlex ID、DOI或ArXiv ID
            count: 返回结果数量
            sort_by: 排序方式,可选值:
                - "relevance": 按相关性排序(默认)
                - "citations": 按引用量排序
                - "date": 按发表日期排序(新到旧)
                - "title": 按标题字母顺序排序
    
        Returns:
            List[Dict]: 引用论文信息列表
        """
        results = []
        try:
            # 设置电子邮件参数(礼貌请求)
            email_param = f"&mailto={EMAIL}" if EMAIL else ""
    
            # 确定API ID
            openalex_id = paper_id
    
            # 如果是DOI或arXiv ID,需要先获取OpenAlex ID
            if paper_id.startswith("10.") or paper_id.lower().startswith("arxiv:"):
                id_type = "doi" if paper_id.startswith("10.") else "arxiv"
                id_value = (
                    paper_id
                    if paper_id.startswith("10.")
                    else paper_id.replace("arxiv:", "")
                )
    
                # 查询以获取OpenAlex ID
                async with httpx.AsyncClient(timeout=10.0) as client:
                    id_response = await client.get(
                        f"{OPENALEX_API}/works/{id_type}:{id_value}?mailto={EMAIL if EMAIL else ''}"
                    )
    
                    if id_response.status_code == 200:
                        id_data = id_response.json()
                        openalex_id = id_data.get("id", "").replace(
                            "https://openalex.org/", ""
                        )
                    else:
                        print(f"获取OpenAlex ID错误: {id_response.status_code}")
                        return []
    
            # 去掉可能的前缀
            if openalex_id.startswith("W"):
                openalex_id = openalex_id[1:]
    
            # 构建引用查询
            citations_url = f"{OPENALEX_API}/works?filter=cites:W{openalex_id}{email_param}&per_page={count}"
    
            # 添加排序方式
            if sort_by == "citations":
                citations_url += "&sort=cited_by_count:desc"
            elif sort_by == "date":
                citations_url += "&sort=publication_date:desc"
            elif sort_by == "title":
                citations_url += "&sort=title:asc"
            # 相关性(relevance)是默认排序,不需要额外参数
    
            async with httpx.AsyncClient(timeout=15.0) as client:
                response = await client.get(citations_url)
    
                if response.status_code == 200:
                    data = response.json()
                    citation_papers = data.get("results", [])
    
                    for paper_data in citation_papers:
                        # 提取论文信息
                        paper = {
                            "title": paper_data.get("title", "未知标题"),
                            "abstract": "",  # 默认为空,稍后处理
                            "citations": paper_data.get("cited_by_count", 0),
                            "year": paper_data.get("publication_year", "未知年份"),
                            "venue": "",  # 需要从期刊/会议信息中提取
                            "paper_id": paper_data.get("id", "").replace(
                                "https://openalex.org/", ""
                            ),
                            "url": paper_data.get("id", ""),
                        }
    
                        # 处理摘要(OpenAlex 摘要是倒排索引格式)
                        if paper_data.get("abstract_inverted_index"):
                            paper["abstract"] = convert_inverted_index_to_text(
                                paper_data.get("abstract_inverted_index", {})
                            )
    
                        # 处理作者信息
                        authors = paper_data.get("authorships", [])
                        author_names = []
                        for author in authors:
                            if author.get("author", {}).get("display_name"):
                                author_names.append(author["author"]["display_name"])
                        paper["authors"] = ", ".join(author_names)
    
                        # 处理期刊/会议信息
                        if paper_data.get("host_venue", {}).get("display_name"):
                            paper["venue"] = paper_data["host_venue"]["display_name"]
    
                        # 处理DOI信息
                        if paper_data.get("doi"):
                            paper["doi"] = paper_data["doi"]
                            paper["doi_url"] = f"https://doi.org/{paper['doi']}"
    
                        results.append(paper)
    
                    return results
                else:
                    print(f"获取论文引用错误: {response.status_code} - {response.text}")
                    return []
    
        except Exception as e:
            print(f"获取论文引用时出错: {str(e)}")
            return []
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses basic behavioral traits: it's a read operation (implied by '获取' - get), returns a list of papers, and has default values and sorting options. However, it lacks details on error handling, rate limits, authentication needs, or what the returned dict structure contains. For a tool with no annotations, this provides minimal but not comprehensive behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and appropriately sized. It starts with a clear purpose statement, followed by organized sections for Args and Returns. Each sentence adds value: the purpose is stated upfront, parameters are explained concisely with defaults and options, and the return type is specified. There's no redundant or wasted information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (3 parameters, no annotations, no output schema), the description is fairly complete. It covers the purpose, all parameters with semantics, and the return type. However, it lacks details on the return value structure (e.g., what keys are in the dict), error cases, or performance considerations. For a tool without annotations or output schema, this is good but not fully comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema, which has 0% description coverage. It explains each parameter: 'paper_id' as the paper ID, 'count' as the number of results with a default of 5, and 'sort_by' with detailed options and their meanings (relevance, citations, date, title). This fully compensates for the schema's lack of descriptions, providing clear semantics for all three parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: '获取引用指定论文的文献列表' (Get a list of papers that reference the specified paper). It uses a specific verb ('获取' - get) and resource ('文献列表' - paper list), but doesn't explicitly differentiate from sibling tools like 'paper_detail' or 'scholar_search'. The purpose is clear but sibling differentiation is only implied through the specific focus on references.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context through the parameter explanations (e.g., '默认为5' - default is 5, '可选值' - optional values), suggesting when certain options might be appropriate. However, it doesn't provide explicit guidance on when to use this tool versus alternatives like 'scholar_search' or 'paper_detail', nor does it mention prerequisites or exclusions. Usage is contextually implied but not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/renyumeng1/mcp_scholar'

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