Skip to main content
Glama
mk965

Asset Price MCP Server

get_asset_price

Retrieve real-time pricing data for assets like precious metals and cryptocurrencies to access and display current market values for informed decision-making.

Instructions

Retrieves current pricing information for various assets including precious metals and cryptocurrencies

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handler function that parses input args, queries multiple price services for the asset symbol(s), applies currency conversion if necessary using the exchange service, handles errors, and returns formatted price information or error messages.
    async (args: any) => {
      const { symbol, currency } = GetAssetPriceArgs.parse(args);
      const targetCurrency = currency.toUpperCase();
      
      const symbolsToQuery = symbol ? [symbol.toUpperCase()] : DEFAULT_ASSETS;
      const results: AssetPrice[] = [];
      const errors: string[] = [];
    
      for (const sym of symbolsToQuery) {
        let found = false;
        let priceData: AssetPrice | null = null;
    
        // Try each service
        for (const service of services) {
            try {
                // First try to get price in requested currency directly (if service supports it)
                // Most of our services default to USD or might ignore currency param if not supported
                priceData = await service.getPrice(sym, targetCurrency);
                
                if (priceData) {
                    // Check if the service returned the price in the requested currency
                    if (priceData.currency.toUpperCase() !== targetCurrency) {
                        // Need conversion
                        const rate = await exchangeService.getRate(priceData.currency, targetCurrency);
                        if (rate) {
                            priceData = {
                                ...priceData,
                                price: priceData.price * rate,
                                currency: targetCurrency,
                                marketCap: priceData.marketCap ? priceData.marketCap * rate : undefined,
                                // Percent change remains the same
                            };
                        } else {
                            // If conversion failed, we keep original currency but maybe warn?
                            // For now, just return original currency price
                        }
                    }
    
                    results.push(priceData);
                    found = true;
                    break;
                }
            } catch (e) {
                console.error(`Error fetching ${sym} from ${service.getName()}:`, e);
            }
        }
        if (!found) {
            errors.push(`Could not find price for ${sym}`);
        }
      }
    
      if (results.length === 0 && errors.length > 0) {
        return {
          content: [{
            type: "text",
            text: `Failed to retrieve prices: ${errors.join(", ")}`
          }],
          isError: true,
        };
      }
    
      return {
        content: [{
          type: "text",
          text: formatPrices(results)
        }]
      };
    }
  • Zod schema defining the input parameters for the get_asset_price tool: optional symbol and currency (default USD).
    const GetAssetPriceArgs = z.object({
      symbol: z.string().optional().describe("The asset symbol to query (e.g., XAU, BTC, AAPL). If omitted, returns a default list of major assets."),
      currency: z.string().default("USD").describe("The currency to express the price in (default: USD)")
    });
  • Function that registers the get_asset_price tool with the MCP server, providing the tool name, description, input schema, and handler function.
    export const registerGetAssetPriceTool = (server: any, services: PriceService[], exchangeService: ExchangeRateService) => {
      server.tool(
        "get_asset_price",
        "Retrieves current pricing information for specific assets or a default list of major assets. Supports automatic currency conversion.",
        GetAssetPriceArgs.shape, 
        async (args: any) => {
          const { symbol, currency } = GetAssetPriceArgs.parse(args);
          const targetCurrency = currency.toUpperCase();
          
          const symbolsToQuery = symbol ? [symbol.toUpperCase()] : DEFAULT_ASSETS;
          const results: AssetPrice[] = [];
          const errors: string[] = [];
    
          for (const sym of symbolsToQuery) {
            let found = false;
            let priceData: AssetPrice | null = null;
    
            // Try each service
            for (const service of services) {
                try {
                    // First try to get price in requested currency directly (if service supports it)
                    // Most of our services default to USD or might ignore currency param if not supported
                    priceData = await service.getPrice(sym, targetCurrency);
                    
                    if (priceData) {
                        // Check if the service returned the price in the requested currency
                        if (priceData.currency.toUpperCase() !== targetCurrency) {
                            // Need conversion
                            const rate = await exchangeService.getRate(priceData.currency, targetCurrency);
                            if (rate) {
                                priceData = {
                                    ...priceData,
                                    price: priceData.price * rate,
                                    currency: targetCurrency,
                                    marketCap: priceData.marketCap ? priceData.marketCap * rate : undefined,
                                    // Percent change remains the same
                                };
                            } else {
                                // If conversion failed, we keep original currency but maybe warn?
                                // For now, just return original currency price
                            }
                        }
    
                        results.push(priceData);
                        found = true;
                        break;
                    }
                } catch (e) {
                    console.error(`Error fetching ${sym} from ${service.getName()}:`, e);
                }
            }
            if (!found) {
                errors.push(`Could not find price for ${sym}`);
            }
          }
    
          if (results.length === 0 && errors.length > 0) {
            return {
              content: [{
                type: "text",
                text: `Failed to retrieve prices: ${errors.join(", ")}`
              }],
              isError: true,
            };
          }
    
          return {
            content: [{
              type: "text",
              text: formatPrices(results)
            }]
          };
        }
      );
    };
  • src/index.ts:28-28 (registration)
    Invocation of the registration function during MCP server initialization, passing the server instance, price services array, and exchange service.
    registerGetAssetPriceTool(server, services, exchangeService);
  • Helper function to format the retrieved AssetPrice objects into a human-readable string with symbol, name, price, change, market cap, and update time.
    function formatPrices(prices: AssetPrice[]): string {
      return prices.map(p => {
        let output = `Symbol: ${p.symbol}\nName: ${p.name}\nPrice: ${p.price.toLocaleString(undefined, { maximumFractionDigits: 2 })} ${p.currency}`;
        if (p.change24h !== undefined) {
            const sign = p.change24h >= 0 ? "+" : "";
            output += `\n24h Change: ${sign}${p.change24h.toFixed(2)}%`;
        }
        if (p.marketCap) {
            output += `\nMarket Cap: ${p.marketCap.toLocaleString(undefined, { maximumFractionDigits: 0 })} ${p.currency}`;
        }
        output += `\nUpdated: ${p.updatedAt}`;
        if (p.updatedAtReadable) {
            output += ` (${p.updatedAtReadable})`;
        }
        return output;
      }).join("\n---\n");
    }
Behavior2/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 states it 'retrieves current pricing information,' implying a read-only operation, but doesn't disclose behavioral traits like rate limits, data freshness, error handling, or authentication needs. This leaves gaps in understanding how the tool behaves.

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 a single, efficient sentence that front-loads the purpose ('retrieves current pricing information') and adds useful detail ('including precious metals and cryptocurrencies'). There's no wasted text, and it's appropriately sized for the tool's simplicity.

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?

Given the tool has no parameters, no annotations, and no output schema, the description is adequate but minimal. It covers the basic purpose but lacks details on output format, data sources, or limitations. For a simple tool, it's passable but could be more complete to aid the agent fully.

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?

The input schema has 0 parameters with 100% coverage, so no parameter documentation is needed. The description doesn't add param info, which is fine here. Baseline is 4 for 0 parameters, as it doesn't need to compensate for any gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('retrieves') and resource ('current pricing information for various assets'), specifying asset types like precious metals and cryptocurrencies. It distinguishes the tool's purpose well, though without sibling tools, differentiation isn't needed. It's not a tautology and is specific enough for understanding.

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?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or context. It mentions asset types but doesn't specify scenarios or limitations. Without siblings, this is less critical, but still lacks usage instructions.

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

Related 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/mk965/asset-price-mcp'

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