Skip to main content
Glama

key_rate

Retrieve Central Bank of Russia key rate time series for a specified date range. Defaults to the most recent 30 days if no dates provided.

Instructions

Get the CBR key-rate (ставка рефинансирования) time series for the requested range. Defaults to the most recent 30 days.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
date_fromNo
date_toNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
date_fromYes
date_toYes
pointsYes
sourceNoЦентральный банк РФ

Implementation Reference

  • Registration of the 'key_rate' MCP tool via @mcp.tool decorator. Maps the tool to tool_key_rate async handler.
    @mcp.tool(
        name="key_rate",
        description=(
            "Get the CBR key-rate (ставка рефинансирования) time series for the"
            " requested range. Defaults to the most recent 30 days."
        ),
    )
    async def tool_key_rate(
        ctx: Context,
        date_from: date | None = None,
        date_to: date | None = None,
    ) -> KeyRateHistory:
        try:
            return await _key_rate(_ctx(ctx), date_from=date_from, date_to=date_to)
        except CbrError as exc:
            raise RuntimeError(_format_error(exc)) from exc
  • Core handler for the 'key_rate' tool. Fetches CBR key-rate series for a date range (default: last 30 days), with caching and validation.
    async def key_rate(
        ctx: ToolContext,
        date_from: date | str | None = None,
        date_to: date | str | None = None,
    ) -> KeyRateHistory:
        """Fetch the CBR key-rate series for the given range (default: last 30 days)."""
        dt = _coerce_date(date_to) or date.today()
        df = _coerce_date(date_from) or (dt - timedelta(days=30))
        if df > dt:
            raise CbrValidationError("date_from must be on or before date_to")
        if (dt - df).days > 365 * 5:
            raise CbrValidationError("key_rate range cannot exceed 5 years")
    
        cache_key = f"keyrate:{df.isoformat()}:{dt.isoformat()}"
        cached = await ctx.history_cache.get(cache_key)
        if cached is not None:
            return cached  # type: ignore[no-any-return]
    
        raw = await ctx.client.fetch_key_rate(df, dt)
        points: list[KeyRatePoint] = []
        for entry in raw:
            try:
                iso = entry["date"][:10]
                point_date = date.fromisoformat(iso)
                rate = _decimal(entry["rate"])
            except Exception:
                logger.debug("skipping malformed key-rate record: %s", entry)
                continue
            points.append(KeyRatePoint(date=point_date, rate=rate))
    
        points.sort(key=lambda p: p.date)
        result = KeyRateHistory(date_from=df, date_to=dt, points=points)
        await ctx.history_cache.set(cache_key, result, ttl=DEFAULT_HISTORY_TTL)
        return result
  • KeyRatePoint schema — one observation in the CBR key-rate series.
    class KeyRatePoint(CbrModel):
        """One observation in the CBR key-rate series."""
    
        date: _dt.date
        rate: Decimal = Field(..., description="Key rate as a percentage, e.g. 16.00.")
  • KeyRateHistory response schema — key-rate observations between date_from and date_to.
    class KeyRateHistory(CbrModel):
        """Key-rate observations between ``date_from`` and ``date_to`` (inclusive)."""
    
        date_from: _dt.date
        date_to: _dt.date
        points: list[KeyRatePoint]
        source: str = DEFAULT_SOURCE
  • CbrClient.fetch_key_rate — makes a SOAP POST to the CBR DailyInfo service and parses <KR> elements with DT/Rate children.
    async def fetch_key_rate(
        self, date_from: date, date_to: date
    ) -> list[dict[str, str]]:
        """Return key-rate observations between ``date_from`` and ``date_to``."""
        envelope = (
            '<?xml version="1.0" encoding="utf-8"?>'
            '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
            ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"'
            ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
            "<soap:Body>"
            '<KeyRateXML xmlns="http://web.cbr.ru/">'
            f"<fromDate>{date_from.isoformat()}</fromDate>"
            f"<ToDate>{date_to.isoformat()}</ToDate>"
            "</KeyRateXML>"
            "</soap:Body>"
            "</soap:Envelope>"
        ).encode()
        headers = {
            "Content-Type": "text/xml; charset=utf-8",
            "SOAPAction": "http://web.cbr.ru/KeyRateXML",
        }
        payload = await self._post(SOAP_URL, envelope, headers=headers)
        root = _parse_xml_bytes(payload)
        # Strip the SOAP envelope to find <KR> nodes anywhere underneath.
        results: list[dict[str, str]] = []
        for kr in root.iter():
            if kr.tag.split("}")[-1] != "KR":
                continue
            dt = ""
            rate = ""
            for child in kr:
                tag = child.tag.split("}")[-1]
                if tag == "DT":
                    dt = (child.text or "").strip()
                elif tag == "Rate":
                    rate = (child.text or "").strip()
            if dt and rate:
                results.append({"date": dt, "rate": rate})
        return results
Behavior3/5

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

No annotations provided, so the description carries the full burden. It implies a read operation ('Get') and time series data, but lacks details on data freshness, time zone, pagination, or whether the operation is safe. The description is not misleading but is minimal.

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?

Two sentences, no redundant information. Front-loaded with the main action and defaults. Every word adds value.

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

Completeness3/5

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

With an output schema present, return values are covered. The description explains the resource (CBR key-rate time series) and default range, but omits time zone, frequency, and any edge cases. Adequate for a simple tool but not fully complete.

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 that parameters define the 'requested range' and notes a default of 30 days, adding some meaning beyond the schema. However, it does not clarify date format, optionality, or parameter semantics beyond this.

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 verb 'Get', the resource 'CBR key-rate time series', and the scope 'for the requested range' with a default of 'most recent 30 days'. This specificity distinguishes it from sibling tools like 'get_rate' (likely a single value) and 'history_rates' (broader).

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

Usage Guidelines2/5

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

No explicit guidance on when to use this tool versus alternatives like 'get_rate' or 'inflation'. The description only states default behavior (30 days) but does not specify prerequisites, scenarios, or exclusions.

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/atomno-labs/mcp-cbr-rates'

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