Skip to main content
Glama
UniRate-API

UniRate MCP

Official
by UniRate-API

Get historical exchange rate (Pro plan required)

historical_rate
Read-only

Retrieve the exchange rate for any currency pair on a specific date, with historical data back to 1999. Requires a Pro subscription.

Instructions

Fetch the exchange rate that was in effect on a specific date. Date format YYYY-MM-DD. Coverage goes back to 1999-01-04 for major fiat pairs. Requires UniRate Pro — free-tier keys will receive a clear upgrade-required error.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dateYesDate in YYYY-MM-DD format, e.g. '2020-03-15'
fromYesSource currency code
toYesTarget currency code
amountNoOptional amount to convert at the historical rate. Defaults to 1.

Implementation Reference

  • The actual API call function that fetches the historical exchange rate from the /api/historical/rates endpoint. Called by the MCP tool handler.
    async getHistoricalRate(date: string, from: string, to: string): Promise<number> {
      const data = await this.request<{ rate?: string; result?: string }>(
        "/api/historical/rates",
        { date, from: from.toUpperCase(), to: to.toUpperCase(), amount: 1 },
      );
      if (data.rate !== undefined) return parseFloat(data.rate);
      if (data.result !== undefined) return parseFloat(data.result);
      throw new APIError("Unexpected historical rate response shape", 500);
    }
  • Helper function that converts an amount at a historical rate (used when amount != 1).
    async convertHistorical(
      date: string,
      from: string,
      to: string,
      amount: number,
    ): Promise<number> {
      const data = await this.request<{ rate?: string; result?: string }>(
        "/api/historical/rates",
        { date, from: from.toUpperCase(), to: to.toUpperCase(), amount },
      );
      if (data.result !== undefined) return parseFloat(data.result);
      if (data.rate !== undefined) return parseFloat(data.rate) * amount;
      throw new APIError("Unexpected historical rate response shape", 500);
    }
  • src/index.ts:116-157 (registration)
    Registration of the 'historical_rate' tool with the MCP server, including input schema (date, from, to, amount) and the handler callback that dispatches to getHistoricalRate or convertHistorical.
    server.registerTool(
      "historical_rate",
      {
        title: "Get historical exchange rate (Pro plan required)",
        description:
          "Fetch the exchange rate that was in effect on a specific date. Date format YYYY-MM-DD. " +
          "Coverage goes back to 1999-01-04 for major fiat pairs. **Requires UniRate Pro** — " +
          "free-tier keys will receive a clear upgrade-required error.",
        inputSchema: {
          date: z
            .string()
            .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD")
            .describe("Date in YYYY-MM-DD format, e.g. '2020-03-15'"),
          from: z.string().min(3).max(10).describe("Source currency code"),
          to: z.string().min(3).max(10).describe("Target currency code"),
          amount: z
            .number()
            .positive()
            .optional()
            .describe("Optional amount to convert at the historical rate. Defaults to 1."),
        },
        annotations: { readOnlyHint: true, openWorldHint: true },
      },
      async ({ date, from, to, amount }) => {
        try {
          if (amount !== undefined && amount !== 1) {
            const result = await client.convertHistorical(date, from, to, amount);
            return ok(
              `On ${date}, ${amount} ${from.toUpperCase()} = ${result} ${to.toUpperCase()}`,
              { date, from: from.toUpperCase(), to: to.toUpperCase(), amount, result },
            );
          }
          const rate = await client.getHistoricalRate(date, from, to);
          return ok(
            `On ${date}, 1 ${from.toUpperCase()} = ${rate} ${to.toUpperCase()}`,
            { date, from: from.toUpperCase(), to: to.toUpperCase(), rate },
          );
        } catch (err) {
          return fail(err);
        }
      },
    );
  • Input schema for the historical_rate tool defining date (YYYY-MM-DD format), from, to, and optional amount parameters with Zod validation.
    inputSchema: {
      date: z
        .string()
        .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD")
        .describe("Date in YYYY-MM-DD format, e.g. '2020-03-15'"),
      from: z.string().min(3).max(10).describe("Source currency code"),
      to: z.string().min(3).max(10).describe("Target currency code"),
      amount: z
        .number()
        .positive()
        .optional()
        .describe("Optional amount to convert at the historical rate. Defaults to 1."),
    },
Behavior4/5

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

Annotations provide readOnlyHint and openWorldHint; description adds coverage start date (1999-01-04) and error behavior for free-tier keys. Does not disclose behavior for out-of-range dates or missing data, but key behavioral context is added beyond 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: first states purpose, second gives format, third adds coverage and requirement. No wasted words, front-loaded with action verb. Perfect structure for quick understanding.

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?

Lacks description of return value (e.g., what is returned if amount is provided). No output schema, so description should hint at response shape. Also, does not specify behavior for missing or invalid dates beyond coverage range. Completeness is adequate but has notable gaps.

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 100% coverage with clear descriptions. Description adds value by stating the coverage start date for the date parameter, which is not in schema. Also reinforces date format. Does not add to other parameters, but schema already sufficient.

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 clearly states it fetches the exchange rate for a specific date, using strong verb 'Fetch' and specific resource. Differentiates from siblings (convert, latest_rate, list_currencies) by focusing on historical data. Mentions date format and coverage range, solidifying purpose.

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

Usage Guidelines5/5

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

Explicitly notes that the tool requires UniRate Pro, including that free-tier keys will receive an error. This is a critical usage condition. Also provides date format and coverage range, helping decide when to use. Does not need to list alternatives as purpose is self-evident.

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/UniRate-API/unirate-mcp'

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