Skip to main content
Glama

article_getter

Retrieve detailed article information, including title, abstract, full text (when available), and source, using PubMed IDs, PMC IDs, or DOIs with BioMCP's tool.

Instructions

Fetch detailed information for a specific article.

Retrieves the full abstract and available text for an article by its identifier.
Supports:
- PubMed IDs (PMID) for published articles
- PMC IDs for articles in PubMed Central
- DOIs for preprints from Europe PMC

Returns formatted text including:
- Title
- Abstract
- Full text (when available from PMC for published articles)
- Source information (PubMed or Europe PMC)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pmidYesArticle identifier - either a PubMed ID (e.g., '38768446' or 'PMC11193658') or DOI (e.g., '10.1101/2024.01.20.23288905')

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • MCP tool registration and handler function for 'article_getter'. Defines input schema via Annotated Field and delegates execution to _article_details.
    @mcp_app.tool()
    @track_performance("biomcp.article_getter")
    async def article_getter(
        pmid: Annotated[
            str,
            Field(
                description="Article identifier - either a PubMed ID (e.g., '38768446' or 'PMC11193658') or DOI (e.g., '10.1101/2024.01.20.23288905')"
            ),
        ],
    ) -> str:
        """Fetch detailed information for a specific article.
    
        Retrieves the full abstract and available text for an article by its identifier.
        Supports:
        - PubMed IDs (PMID) for published articles
        - PMC IDs for articles in PubMed Central
        - DOIs for preprints from Europe PMC
    
        Returns formatted text including:
        - Title
        - Abstract
        - Full text (when available from PMC for published articles)
        - Source information (PubMed or Europe PMC)
        """
        return await _article_details(
            call_benefit="Fetch detailed article information for analysis",
            pmid=pmid,
        )
  • Core helper function implementing the article fetching logic. Determines if PMID or DOI and calls appropriate APIs (PubTator3 or Europe PMC).
    async def _article_details(
        call_benefit: Annotated[
            str,
            "Define and summarize why this function is being called and the intended benefit",
        ],
        pmid,
    ) -> str:
        """
        Retrieves details for a single article given its identifier.
    
        Parameters:
        - call_benefit: Define and summarize why this function is being called and the intended benefit
        - pmid: An article identifier - either a PubMed ID (e.g., 34397683) or DOI (e.g., 10.1101/2024.01.20.23288905)
    
        Process:
        - For PMIDs: Calls the PubTator3 API to fetch the article's title, abstract, and full text (if available)
        - For DOIs: Calls Europe PMC API to fetch preprint details
    
        Output: A JSON formatted string containing the retrieved article content.
        """
        identifier = str(pmid)
    
        # Check if it's a DOI (Europe PMC preprint)
        if is_doi(identifier):
            from .preprints import fetch_europe_pmc_article
    
            return await fetch_europe_pmc_article(identifier, output_json=True)
        # Check if it's a PMID (PubMed article)
        elif is_pmid(identifier):
            return await fetch_articles(
                [int(identifier)], full=True, output_json=True
            )
        else:
            # Unknown identifier format
            return json.dumps(
                [
                    {
                        "error": f"Invalid identifier format: {identifier}. Expected either a PMID (numeric) or DOI (10.xxxx/xxxx format)."
                    }
                ],
                indent=2,
            )
  • Pydantic models defining the structure of fetched article data, including computed fields for title, abstract, full_text, and URLs.
    class Article(BaseModel):
        pmid: int | None = Field(
            None,
            description="PubMed ID of the reference article.",
        )
        pmcid: str | None = Field(
            None,
            description="PubMed Central ID of the reference article.",
        )
        date: str | None = Field(
            None,
            description="Date of the reference article's publication.",
        )
        journal: str | None = Field(
            None,
            description="Journal name.",
        )
        authors: list[str] | None = Field(
            None,
            description="List of authors.",
        )
        passages: list[Passage] = Field(
            ...,
            alias="passages",
            description="List of passages in the reference article.",
            exclude=True,
        )
    
        @computed_field
        def title(self) -> str:
            lines = []
            for passage in filter(lambda p: p.is_title, self.passages):
                if passage.text:
                    lines.append(passage.text)
            return " ... ".join(lines) or f"Article: {self.pmid}"
    
        @computed_field
        def abstract(self) -> str:
            lines = []
            for passage in filter(lambda p: p.is_abstract, self.passages):
                if passage.text:
                    lines.append(passage.text)
            return "\n\n".join(lines) or f"Article: {self.pmid}"
    
        @computed_field
        def full_text(self) -> str:
            lines = []
            for passage in filter(lambda p: p.is_text, self.passages):
                if passage.text:
                    lines.append(passage.text)
            return "\n\n".join(lines) or ""
    
        @computed_field
        def pubmed_url(self) -> str | None:
            url = None
            if self.pmid:
                url = f"https://pubmed.ncbi.nlm.nih.gov/{self.pmid}/"
            return url
    
        @computed_field
        def pmc_url(self) -> str | None:
            """Generates the PMC URL if PMCID exists."""
            url = None
            if self.pmcid:
                url = f"https://www.ncbi.nlm.nih.gov/pmc/articles/{self.pmcid}/"
            return url
  • Helper function that calls PubTator3 API to fetch article full text and handles response formatting.
    async def fetch_articles(
        pmids: list[int],
        full: bool,
        output_json: bool = False,
    ) -> str:
        """Fetch the text of a list of PubMed IDs."""
    
        response, error = await call_pubtator_api(pmids, full)
    
        # PubTator API returns full text even when full=False
        exclude_fields = {"full_text"} if not full else set()
    
        # noinspection DuplicatedCode
        if error:
            data: list[dict[str, Any]] = [
                {"error": f"Error {error.code}: {error.message}"}
            ]
        else:
            data = [
                article.model_dump(
                    mode="json",
                    exclude_none=True,
                    exclude=exclude_fields,
                )
                for article in (response.articles if response else [])
            ]
    
        if data and not output_json:
            return render.to_markdown(data)
        else:
            return json.dumps(data, indent=2)
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It does well by describing what information is returned (title, abstract, full text when available, source) and specifying availability conditions ('when available from PMC for published articles'). However, it doesn't mention potential limitations like rate limits, authentication needs, or error conditions.

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, then provides supporting details about identifier types and return format in bullet points. Every sentence earns its place with no wasted words or redundancy.

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 (single parameter, read-only operation), the description is reasonably complete. It explains what the tool does, what identifiers it accepts, and what information it returns. With an output schema presumably documenting the return structure, the description doesn't need to fully explain return values. The main gap is lack of behavioral constraints disclosure.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already fully documents the single 'pmid' parameter with examples. The description adds some semantic context by listing the specific identifier types supported (PubMed IDs, PMC IDs, DOIs), which complements but doesn't significantly expand beyond what the schema provides. Baseline 3 is appropriate when schema does the heavy lifting.

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

Purpose5/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 with specific verbs ('fetch detailed information', 'retrieves full abstract and available text') and identifies the resource ('article by its identifier'). It distinguishes from sibling tools like 'article_searcher' by focusing on retrieving details for a specific article rather than searching for multiple articles.

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

Usage Guidelines4/5

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

The description provides clear context for when to use this tool by specifying the types of identifiers supported (PubMed IDs, PMC IDs, DOIs) and indicating it's for fetching detailed information about a specific article. However, it doesn't explicitly state when NOT to use it or mention alternatives like 'article_searcher' for broader searches.

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/genomoncology/biomcp'

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