Skip to main content
Glama
gtorreal
by gtorreal

get_price_history

Retrieve OHLCV candle history for any Buda market. Choose period (5m to 1d) and adjust trade count for depth.

Instructions

IMPORTANT: Candles are aggregated client-side from raw trades (Buda has no native candlestick endpoint) — fetching more trades via the 'limit' parameter gives deeper history but slower responses. Returns OHLCV candles (open/high/low/close as floats in quote currency; volume as float in base currency) for periods 5m, 15m, 30m, 1h, 4h, or 1d. Candle timestamps are UTC bucket boundaries. Example: 'Show me the hourly BTC-CLP price chart for the past 24 hours.'

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
market_idYesMarket ID (e.g. 'BTC-CLP', 'ETH-BTC').
periodNoCandle period: '5m', '15m', '30m', '1h', '4h', or '1d'. Default: '1h'.1h
limitNoRaw trades to fetch before aggregation (default: 100, max: 1000). More trades = deeper history but slower response.

Implementation Reference

  • Handler function that registers the get_price_history tool. Fetches raw trades from Buda API (/markets/{id}/trades), then aggregates them client-side into OHLCV candles using aggregateTradesToCandles(). Validates market_id, accepts optional period (default 1h) and limit (default 100, max 1000).
    export function register(server: McpServer, client: BudaClient, _cache: MemoryCache): void {
      server.tool(
        toolSchema.name,
        toolSchema.description,
        {
          market_id: z
            .string()
            .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
          period: z
            .enum(["5m", "15m", "30m", "1h", "4h", "1d"])
            .default("1h")
            .describe("Candle period: '5m', '15m', '30m', '1h', '4h', or '1d'. Default: '1h'."),
          limit: z
            .number()
            .int()
            .min(1)
            .max(1000)
            .optional()
            .describe(
              "Raw trades to fetch before aggregation (default: 100, max: 1000). " +
                "More trades = deeper history but slower response.",
            ),
        },
        async ({ market_id, period, limit }) => {
          try {
            const validationError = validateMarketId(market_id);
            if (validationError) {
              return {
                content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_MARKET_ID" }) }],
                isError: true,
              };
            }
    
            const id = market_id.toLowerCase();
            const tradesLimit = limit ?? 100;
    
            const data = await client.get<TradesResponse>(
              `/markets/${id}/trades`,
              { limit: tradesLimit },
            );
    
            const entries = data.trades.entries;
            if (entries.length === 0) {
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify({ market_id: market_id.toUpperCase(), period, candles: [] }),
                  },
                ],
              };
            }
    
            const candles = aggregateTradesToCandles(entries, period);
    
            const result = {
              market_id: market_id.toUpperCase(),
              period,
              candle_count: candles.length,
              trades_fetched: entries.length,
              note:
                "Candles derived from raw trade history. Candle timestamps are UTC bucket boundaries. " +
                "Increase 'limit' (max 1000) for deeper history.",
              candles,
            };
    
            return {
              content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
            };
          } catch (err) {
            const msg = formatApiError(err);
            return {
              content: [{ type: "text", text: JSON.stringify(msg) }],
              isError: true,
            };
          }
        },
      );
    }
  • Schema definition for get_price_history tool: name, description, and JSON Schema input with market_id (required string), period (optional string), and limit (optional number).
    export const toolSchema = {
      name: "get_price_history",
      description:
        "IMPORTANT: Candles are aggregated client-side from raw trades (Buda has no native candlestick " +
        "endpoint) — fetching more trades via the 'limit' parameter gives deeper history but slower " +
        "responses. Returns OHLCV candles (open/high/low/close as floats in quote currency; volume as float " +
        "in base currency) for periods 5m, 15m, 30m, 1h, 4h, or 1d. Candle timestamps are UTC bucket boundaries. " +
        "Example: 'Show me the hourly BTC-CLP price chart for the past 24 hours.'",
      inputSchema: {
        type: "object" as const,
        properties: {
          market_id: {
            type: "string",
            description: "Market ID (e.g. 'BTC-CLP', 'ETH-BTC').",
          },
          period: {
            type: "string",
            description: "Candle period: '5m', '15m', '30m', '1h', '4h', or '1d'. Default: '1h'.",
          },
          limit: {
            type: "number",
            description:
              "Raw trades to fetch before aggregation (default: 100, max: 1000). " +
              "More trades = deeper history but slower response.",
          },
        },
        required: ["market_id"],
      },
    };
  • src/index.ts:43-43 (registration)
    Registration of the get_price_history tool in the main entrypoint (stdio server).
    priceHistory.register(server, client, cache);
  • src/http.ts:88-88 (registration)
    Registration of the get_price_history tool in the HTTP/Express server entrypoint.
    priceHistory.register(server, client, reqCache);
  • Helper function that aggregates raw trade entries into OHLCV candles for a given period. Sorts trades, buckets by period boundaries, and computes open/high/low/close/volume per bucket.
    export function aggregateTradesToCandles(
      entries: [string, string, string, string][],
      period: string,
    ): OhlcvCandle[] {
      const periodMs = PERIOD_MS[period];
      if (!periodMs) throw new Error(`Unknown period: ${period}`);
    
      const sorted = [...entries].sort(([a], [b]) => parseInt(a, 10) - parseInt(b, 10));
      const buckets = new Map<number, OhlcvCandle>();
    
      for (const [tsMs, amount, price] of sorted) {
        const ts = parseInt(tsMs, 10);
        const bucketStart = Math.floor(ts / periodMs) * periodMs;
        const p = parseFloat(price);
        const v = parseFloat(amount);
    
        if (!buckets.has(bucketStart)) {
          buckets.set(bucketStart, {
            time: new Date(bucketStart).toISOString(),
            open: p,
            high: p,
            low: p,
            close: p,
            volume: v,
            trade_count: 1,
          });
        } else {
          const candle = buckets.get(bucketStart)!;
          if (p > candle.high) candle.high = p;
          if (p < candle.low) candle.low = p;
          candle.close = p;
          candle.volume = parseFloat((candle.volume + v).toFixed(8));
          candle.trade_count++;
        }
      }
    
      return Array.from(buckets.entries())
        .sort(([a], [b]) => a - b)
        .map(([, candle]) => candle);
    }
Behavior4/5

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

With no annotations, the description carries full burden. It discloses that candles are aggregated client-side from raw trades (a key behavioral detail) and explains performance implications of the limit parameter. It also specifies the return format (OHLCV floats) and valid periods.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is slightly long but front-loaded with important warnings. Each sentence adds value: warning about aggregation, output format, valid periods, and example. Could be slightly more concise but achieves good clarity.

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 no output schema, the description explains the return format thoroughly. It covers all parameters and provides usage context. It lacks discussion of error cases (e.g., invalid market_id) but is otherwise complete for a read-only tool.

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 coverage is 100%, so baseline is 3. The description adds value by explaining the limit parameter's performance trade-off and providing an example. It also restates period options, reinforcing schema information.

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 it returns OHLCV candles aggregated from raw trades for specific periods. It distinguishes itself from sibling tools like get_trades (raw trades) and get_ticker (current price) by explaining the client-side aggregation and the candle format.

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 includes an example and explains the trade-off for the limit parameter (deeper history vs slower response). It implicitly suggests when to use this tool (for candlestick data) and when not (if raw trades are needed, use get_trades). However, it does not explicitly name alternatives.

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/gtorreal/buda-mcp'

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