Skip to main content
Glama
atmospore

Atmospore

Official

get_area_average

Retrieve daily tree, grass, and weed pollen aggregates over a radius to compare pollen levels and trends over the forecast period.

Instructions

Get tree, grass, and weed pollen aggregates over a radius around a point.

Use this for higher-level questions like "is tree or grass pollen worse this week?" or "is pollen rising over the next few days in Stockholm?". Returns one entry per day with overall_risk and per-category aggregates (tree_tot, grass_tot, weed_tot).

radius_km (default 25) controls the area. forecast_days (default 7) sets the horizon.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
latYes
lonYes
radius_kmNo
forecast_daysNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handler function for the get_area_average tool. Calls client.pollen_area with lat, lon, radius_km, forecast_days, and species filters (tree_tot, grass_tot, weed_tot). Returns per-day data with overall_risk and per-category aggregates.
    @mcp.tool(description=GET_AREA_AVERAGE_DESCRIPTION)
    async def get_area_average(
        lat: float,
        lon: float,
        radius_km: float = 25,
        forecast_days: int = 7,
    ) -> dict[str, Any]:
        async def call() -> Any:
            days = await client.pollen_area(
                lat=lat,
                lon=lon,
                radius_km=radius_km,
                forecast_days=forecast_days,
                species=["tree_tot", "grass_tot", "weed_tot"],
            )
            return [
                {
                    "date": d.date,
                    "overall_risk": d.overall_risk,
                    "categories": {
                        cat: {
                            "value": lvl.value,
                            "units": lvl.units,
                            "risk_level": lvl.risk_level,
                        }
                        for cat, lvl in d.pollen_levels.items()
                    },
                }
                for d in days
            ]
    
        return await _safe_call(call())
  • Description/schema for the get_area_average tool, documenting its purpose, return shape, and default parameter values.
    GET_AREA_AVERAGE_DESCRIPTION = """Get tree, grass, and weed pollen aggregates over a radius around a point.
    
    Use this for higher-level questions like "is tree or grass pollen worse this week?" or
    "is pollen rising over the next few days in Stockholm?". Returns one entry per day with
    overall_risk and per-category aggregates (tree_tot, grass_tot, weed_tot).
    
    `radius_km` (default 25) controls the area. `forecast_days` (default 7) sets the horizon."""
  • Registration of get_area_average as an MCP tool via the @mcp.tool decorator, with the description from GET_AREA_AVERAGE_DESCRIPTION.
    @mcp.tool(description=GET_AREA_AVERAGE_DESCRIPTION)
    async def get_area_average(
  • The _safe_call helper used by get_area_average (and all tools) to wrap client calls and normalize errors (authentication, quota, API, unexpected) into a structured dict 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)}
Behavior2/5

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

Description lacks behavioral traits such as idempotency, side effects, or authentication needs. It only explains output structure and parameter defaults, which is minimal for a tool with no annotations.

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?

Three sentences, front-loaded with purpose, and every sentence adds value. No redundancy or fluff.

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?

Output schema exists (not shown) but description explains return structure adequately. Parameter coverage is sufficient for operation, though lacks error or behavior details.

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

Parameters4/5

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

Schema has 0% description coverage, but description adds meaning by explaining radius_km controls the area and forecast_days sets the horizon. However, lat and lon are not explicitly described, though implied by context.

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?

Description uses specific verb 'Get' and resource 'pollen aggregates over a radius' and distinguishes from siblings by framing it for higher-level questions, clearly indicating its focus on area aggregates over time.

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?

Description explicitly states when to use the tool with examples ('is tree or grass pollen worse this week?') and implies it is for area-based queries rather than point-specific data, but does not directly mention when not to use or compare to siblings like get_pollen.

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