Skip to main content
Glama
atmospore

Atmospore

Official

get_top_species

Identify the top pollen species at any location today. Get a ranked list of species with their concentration levels and risk categories.

Instructions

Get the top contributing pollen species at a specific point today.

Use this to answer "what pollen is highest in Oslo right now?" or "which trees are blooming in Bergen?". Returns a ranked list (highest first). Each species includes:

  • species (slug, e.g. 'birch')

  • display_name (human-readable, e.g. 'Birch')

  • max_value in grains/m³

  • risk_level

  • category ('tree' | 'grass' | 'weed')

limit (default 5) caps the list length.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
latYes
lonYes
limitNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The get_top_species tool handler function. An async function decorated with @mcp.tool that calls client.pollen_top(lat, lon, limit) and returns a ranked list of species with display_name, category, max_value, units, and risk_level. Wrapped in _safe_call for error handling.
    @mcp.tool(description=GET_TOP_SPECIES_DESCRIPTION)
    async def get_top_species(lat: float, lon: float, limit: int = 5) -> dict[str, Any]:
        async def call() -> Any:
            top = await client.pollen_top(lat=lat, lon=lon, limit=limit)
            return [
                {
                    "species": s.species,
                    "display_name": s.display_name,
                    "category": s.category,
                    "max_value": s.max_value,
                    "units": s.units,
                    "risk_level": s.risk_level,
                }
                for s in top
            ]
    
        return await _safe_call(call())
  • GET_TOP_SPECIES_DESCRIPTION — documentation string describing input params (lat, lon, limit=5) and output shape (species, display_name, max_value, risk_level, category). Used by the LLM during MCP handshake.
    GET_TOP_SPECIES_DESCRIPTION = """Get the top contributing pollen species at a specific point today.
    
    Use this to answer "what pollen is highest in Oslo right now?" or "which trees are blooming in
    Bergen?". Returns a ranked list (highest first). Each species includes:
    - species (slug, e.g. 'birch')
    - display_name (human-readable, e.g. 'Birch')
    - max_value in grains/m³
    - risk_level
    - category ('tree' | 'grass' | 'weed')
    
    `limit` (default 5) caps the list length."""
  • Tool registration via @mcp.tool(description=GET_TOP_SPECIES_DESCRIPTION) decorator on the get_top_species function inside build_server().
    @mcp.tool(description=GET_TOP_SPECIES_DESCRIPTION)
  • _safe_call helper — wraps async client calls to catch AuthenticationError, RateLimitError, APIError, and unexpected exceptions, returning structured dicts with ok/error/message for the LLM.
    async def _safe_call(coro) -> dict[str, Any]:
        """Wrap a client call so structured errors reach the LLM cleanly."""
        try:
            return {"ok": True, "data": await coro}
        except AuthenticationError as e:
            return {
                "ok": False,
                "error": "authentication_failed",
                "message": str(e),
                "hint": "Check ATMOSPORE_API_KEY. Get a free key at https://atmospore.com/account.",
            }
        except RateLimitError as e:
            return {
                "ok": False,
                "error": "quota_exceeded",
                "message": str(e),
                "limit": e.limit,
                "used": e.used,
                "resets_at": e.resets_at,
                "hint": "Daily quota hit. Upgrade at https://atmospore.com/plans for higher limits.",
            }
        except APIError as e:
            return {
                "ok": False,
                "error": "api_error",
                "status": e.status,
                "message": str(e),
            }
        except Exception as e:  # noqa: BLE001 — surface unknown errors to LLM
            logger.exception("Unexpected error in MCP tool")
            return {"ok": False, "error": "unexpected_error", "message": str(e)}
Behavior4/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 the output structure (species, display_name, max_value, risk_level, category) and time specificity (today). However, it lacks explicit mention of being read-only or non-destructive, though the read nature is implied.

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 concise: a lead sentence stating the purpose, followed by a short list of output fields and one additional note about the limit parameter. Every sentence earns its place.

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 simplicity and the presence of an output schema, the description adequately explains the return values and default behavior. It could be improved by noting timezone or edge cases (e.g., no data), but is sufficient for correct usage.

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 0%, so the description must compensate. It explains the limit parameter's default and function, but provides no additional meaning for lat/lon beyond their names. This partially adds value but leaves a gap for the required coordinates.

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 'Get the top contributing pollen species at a specific point today,' specifying a verb, resource, location, and time. This distinguishes it from sibling tools like get_area_average (averages) and get_pollen (all species).

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?

Provides concrete usage examples ('what pollen is highest in Oslo right now?') and states it returns a ranked list. While it doesn't explicitly say when not to use, the context of sibling tools implies alternatives for different queries.

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

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/atmospore/atmospore-mcp'

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