Skip to main content
Glama
jun229

truemarkets-mcp-server

by jun229

Get a trade quote

tm_get_quote
Read-only

Get a fixed-price quote for token trades to verify exact costs before executing. Returns pricing details and a time-limited quote ID for secure trade confirmation.

Instructions

Request a quote for buying or selling a token. Returns pricing info and a quote_id that can be passed to tm_execute_trade within 60 seconds.

IMPORTANT: Always call this BEFORE tm_execute_trade. Inspect the quote (price, fee, issues) and only execute if acceptable. This solves the price uncertainty problem — you see the exact price you'll get.

Args:

  • side ("buy" | "sell"): Trade direction

  • token (string): Token symbol (SOL, ETH) or contract address

  • amount (string): Quantity as a decimal string

  • chain ("solana" | "base"): Blockchain network (default: solana)

  • qty_unit ("base" | "quote"): What the amount represents (default: "quote" for buy, "base" for sell)

Returns: { quote_id: string, // Pass this to tm_execute_trade side, token, chain, you_pay: string, // Amount + asset you send you_receive: string, // Amount + asset you get fee: string, effective_price: string, // USDC per token issues: [], // Any problems (e.g. insufficient balance) expires_in_seconds: 60 }

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sideYesBuy or sell
tokenYesToken symbol or contract address
amountYesQuantity as decimal string
chainNoChainsolana
qty_unitNoWhat amount represents. Default: 'quote' (USDC) for buy, 'base' (token) for sell

Implementation Reference

  • The handler logic for tm_get_quote, which fetches a quote from the API and caches it.
    async ({ side, token, amount, chain, qty_unit }) => {
      // Resolve symbol
      let baseAsset = token;
      let resolvedChain = chain;
    
      if (isSymbol(token)) {
        const assets = await api.getAssets();
        const match = assets.find(
          (a) => a.symbol?.toLowerCase() === token.toLowerCase()
        );
        if (!match?.address) {
          return {
            isError: true,
            content: [{ type: "text", text: `Could not resolve symbol "${token}". Use tm_list_assets to see available tokens.` }],
          };
        }
        baseAsset = match.address;
        if (match.chain) resolvedChain = match.chain.toLowerCase() as "solana" | "base";
      }
    
      const quote = await api.createQuote({
        order_side: side,
        chain: resolvedChain,
        base_asset: baseAsset,
        quote_asset: getQuoteAsset(resolvedChain),
        qty: amount,
      });
    
      // Cache the quote so tm_execute_trade can use the same one
      cacheQuote(quote);
    
      // Compute effective price
      const qty = parseFloat(quote.qty);
      const qtyOut = parseFloat(quote.qty_out);
      const effectivePrice = side === "buy"
        ? (qty / qtyOut).toFixed(6)
        : (qtyOut / qty).toFixed(6);
    
      const output = {
        quote_id: quote.quote_id,
        side,
        token: token.toUpperCase(),
        chain: resolvedChain,
        you_pay: `${quote.qty} ${side === "buy" ? "USDC" : token.toUpperCase()}`,
        you_receive: `${quote.qty_out} ${side === "buy" ? token.toUpperCase() : "USDC"}`,
        fee: `${quote.fee} ${quote.fee_asset}`,
        effective_price: `${effectivePrice} USDC/${token.toUpperCase()}`,
        issues: quote.issues.map((i) => ({
          message: i.message,
          ...(i.balance ? { have: i.balance.actual, need: i.balance.expected } : {}),
        })),
        has_issues: quote.issues.length > 0,
        expires_in_seconds: 60,
      };
    
      return {
        content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
        structuredContent: output,
      };
    }
  • Registration and schema definition for the tm_get_quote tool.
      server.registerTool(
        "tm_get_quote",
        {
          title: "Get a trade quote",
          description: `Request a quote for buying or selling a token. Returns pricing info
    and a quote_id that can be passed to tm_execute_trade within 60 seconds.
    
    IMPORTANT: Always call this BEFORE tm_execute_trade. Inspect the quote
    (price, fee, issues) and only execute if acceptable. This solves the
    price uncertainty problem — you see the exact price you'll get.
    
    Args:
      - side ("buy" | "sell"): Trade direction
      - token (string): Token symbol (SOL, ETH) or contract address
      - amount (string): Quantity as a decimal string
      - chain ("solana" | "base"): Blockchain network (default: solana)
      - qty_unit ("base" | "quote"): What the amount represents (default: "quote" for buy, "base" for sell)
    
    Returns: {
      quote_id: string,       // Pass this to tm_execute_trade
      side, token, chain,
      you_pay: string,        // Amount + asset you send
      you_receive: string,    // Amount + asset you get
      fee: string,
      effective_price: string, // USDC per token
      issues: [],             // Any problems (e.g. insufficient balance)
      expires_in_seconds: 60
    }`,
          inputSchema: {
            side: z.enum(["buy", "sell"]).describe("Buy or sell"),
            token: z.string().describe("Token symbol or contract address"),
            amount: z.string().describe("Quantity as decimal string"),
            chain: z.enum(["solana", "base"]).default("solana").describe("Chain"),
            qty_unit: z.enum(["base", "quote"]).optional()
              .describe("What amount represents. Default: 'quote' (USDC) for buy, 'base' (token) for sell"),
          },
          annotations: {
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: false,
            openWorldHint: true,
          },
        },
Behavior4/5

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

The description adds valuable behavioral context beyond annotations. While annotations indicate readOnlyHint=true (non-destructive) and openWorldHint=true, the description specifies the 60-second expiration window ('quote_id that can be passed to tm_execute_trade within 60 seconds'), which is critical for timing behavior. It also mentions inspecting 'issues' like insufficient balance, adding practical constraints. No contradiction with annotations exists.

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 well-structured and front-loaded: the first sentence states the core purpose, followed by critical usage guidelines, and then details on parameters and returns. Every sentence serves a clear purpose—no wasted words. The bullet-point format for Args and Returns improves readability without verbosity.

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

Completeness5/5

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

Given the tool's complexity (trade quoting with financial implications) and the absence of an output schema, the description provides comprehensive context. It fully documents the return structure, including all fields like quote_id, you_pay, you_receive, fee, and expiration details. This compensates for the lack of structured output schema, ensuring the agent understands what to expect.

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?

With 100% schema description coverage, the baseline is 3. The description adds meaningful context: it explains the purpose of qty_unit with defaults ('default: "quote" for buy, "base" for sell'), clarifies that amount is a 'decimal string', and provides examples for token ('SOL, ETH'). This enhances understanding beyond the schema's technical definitions.

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 explicitly states the purpose: 'Request a quote for buying or selling a token.' It specifies the verb ('Request a quote') and resource ('token'), and distinguishes it from sibling tools like tm_execute_trade by emphasizing this is a preparatory step. The description clearly differentiates this tool from tm_get_price by focusing on actionable quotes rather than just price information.

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?

The description provides explicit usage guidelines: 'Always call this BEFORE tm_execute_trade. Inspect the quote (price, fee, issues) and only execute if acceptable.' It names the alternative tool (tm_execute_trade) and specifies when to use this tool versus when to proceed with execution. The context of solving 'the price uncertainty problem' further clarifies its role.

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/jun229/tm-mcp-server'

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