Skip to main content
Glama
PaulieB14

Limitless MCP

search_markets

Find markets by keyword or category with enriched on-chain data including volume and trade counts.

Instructions

Search markets by keyword or category. Returns market metadata enriched with on-chain volume and trade counts from subgraphs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryNoKeyword to search in title/description
categoriesNoFilter by categories (e.g. ['Crypto', 'Politics'])
firstNoNumber of results to return

Implementation Reference

  • The handler for the search_markets tool, which invokes the apiClient's searchMarkets function and then enriches the results with subgraph data.
    async ({ query, categories, first }) => {
      try {
        const apiResults = await searchMarkets(query, categories, first);
    
        // Enrich each result with on-chain stats from subgraphs
        const enriched = await Promise.all(
          apiResults.map(async (m) => {
            const mq = (entity: string) =>
              `{ ${entity}(id: "${m.conditionId}") { tradesCount volumeUSD feesUSD } }`;
            const [s, n] = await Promise.all([
              querySimple(mq("market")).catch(() => ({ market: null })),
              queryNegRisk(mq("negRiskMarket")).catch(() => ({ negRiskMarket: null })),
            ]);
            const onChain = s.market || n.negRiskMarket;
            return {
              title: m.title,
              conditionId: m.conditionId,
              categories: m.categories,
              currentPrices: m.prices,
              expirationDate: m.expirationDate,
              marketType: m.marketType,
              tradeType: m.tradeType,
              status: m.status,
              onChainVolume: onChain?.volumeUSD || "0",
              onChainTrades: onChain?.tradesCount || "0",
              onChainFees: onChain?.feesUSD || "0",
            };
          })
        );
    
        return textResult({ count: enriched.length, markets: enriched });
      } catch (e) {
        return errorResult(e);
      }
    }
  • The implementation of searchMarkets in apiClient.ts, which fetches from the API and filters cached markets.
    export async function searchMarkets(
      query?: string,
      categories?: string[],
      first = 20
    ): Promise<MarketMeta[]> {
      // If there's a query, also try the API search endpoint for broader results
      if (query) {
        const headers = getHeaders();
        try {
          const res = await fetch(
            `${LIMITLESS_API_BASE}/markets/search?query=${encodeURIComponent(query)}`,
            { headers }
          );
          if (res.ok) {
            const json = (await res.json()) as { markets: any[] };
            for (const m of json.markets || []) {
              const meta = toMarketMeta(m);
              if (meta) marketCache.set(meta.conditionId.toLowerCase(), meta);
            }
          }
        } catch {
          // Fall back to cache-only search
        }
      }
    
      await refreshMarketCache();
      let results = Array.from(marketCache.values());
    
      if (query) {
        const q = query.toLowerCase();
        results = results.filter(
          (m) =>
            m.title.toLowerCase().includes(q) ||
            m.description.toLowerCase().includes(q) ||
            m.slug.toLowerCase().includes(q)
        );
      }
    
      if (categories && categories.length > 0) {
        const cats = categories.map((c) => c.toLowerCase());
        results = results.filter((m) =>
          m.categories.some((c) => cats.includes(c.toLowerCase()))
        );
      }
    
      return results.slice(0, first);
    }
  • Registration of the search_markets tool in the MCP server.
    server.registerTool(
      "search_markets",
      {
        description:
          "Search markets by keyword or category. Returns market metadata enriched with on-chain volume and trade counts from subgraphs.",
        inputSchema: {
          query: z.string().optional().describe("Keyword to search in title/description"),
          categories: z
            .array(z.string())
            .optional()
            .describe("Filter by categories (e.g. ['Crypto', 'Politics'])"),
          first: z.number().default(20).describe("Number of results to return"),
        },
      },

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/PaulieB14/limitless-subgraphs'

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