Skip to main content
Glama

get_deals

Find discounted PC component deals with current prices and 90-day price history. Filter by category to compare hardware offers across Brazilian stores.

Instructions

Ofertas atuais com desconto no meupc.net, com preço atual e menor preço em 90 dias

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageNoNúmero da página
categoryNoFiltrar por categoria (ex: 'processadores', 'placas-video', 'memorias')

Implementation Reference

  • Main handler function getDeals that fetches deals from meupc.net, parses HTML to extract product information (name, price, discount, store), and returns results as JSON.
    export async function getDeals(params: GetDealsParams): Promise<string> {
      const { page, category } = params;
    
      let url = `/ofertas?page=${page}`;
      if (category) {
        url += `&peca=${encodeURIComponent(category)}`;
      }
    
      const $ = await fetchPage(url);
      const results: DealResult[] = [];
    
      $("div.card.is-fullheight").each((_, el) => {
        const $card = $(el);
    
        const name = $card.find(".card-content h3.title a").text().trim();
        if (!name) return;
    
        const productUrl = $card.find(".card-content h3.title a").attr("href") ?? "";
    
        const image = $card.find("header.card-image figure img").attr("src") ?? null;
    
        // Loja
        const store = $card.find(".card-content p.uppertitle").text().trim()
          || $card.find("header.card-image div.loja-img img").attr("alt")?.trim()
          || null;
    
        // Desconto (tag vermelha, ex: "-50%")
        const discount = $card.find(".card-content span.tag.is-danger").text().trim() || null;
    
        // Preço atual
        const currentPriceText = $card.find(".card-content a.preco").text().trim();
        const currentPrice = parsePrice(currentPriceText) ?? 0;
    
        // Menor preço em 90 dias (no div.level.is-fullwidth)
        const levels = $card.find(".card-content div.level.is-fullwidth");
        let oldPrice: number | null = null;
    
        levels.each((_, lvl) => {
          const text = $(lvl).text();
          if (text.includes("Menor") || text.includes("90 dias")) {
            const priceMatch = text.match(/R\$\s*([\d.,]+)/);
            if (priceMatch) {
              oldPrice = parsePrice(priceMatch[1]);
            }
          }
        });
    
        results.push({
          name,
          currentPrice,
          oldPrice,
          discount,
          store,
          url: absoluteUrl(productUrl),
          image: image ? absoluteUrl(image) : null,
        });
      });
    
      return JSON.stringify(results, null, 2);
    }
  • Input schema getDealsSchema defining the parameters (page number with default 1, optional category filter) and type definition GetDealsParams.
    export const getDealsSchema = z.object({
      page: z.number().int().positive().default(1).describe("Número da página"),
      category: z.string().optional().describe("Filtrar por categoria (ex: 'processadores', 'placas-video', 'memorias')"),
    });
    
    export type GetDealsParams = z.infer<typeof getDealsSchema>;
  • src/index.ts:43-50 (registration)
    Tool registration for 'get_deals' with description, schema reference, and handler call wrapping getDeals function.
    server.tool(
      "get_deals",
      "Ofertas atuais com desconto no meupc.net, com preço atual e menor preço em 90 dias",
      getDealsSchema.shape,
      async (params) => ({
        content: [{ type: "text", text: await getDeals(params) }],
      })
    );
  • Output type interface DealResult defining the structure of deal objects (name, currentPrice, oldPrice, discount, store, url, image).
    export interface DealResult {
      name: string;
      currentPrice: number;
      oldPrice: number | null;
      discount: string | null;
      store: string | null;
      url: string;
      image: string | null;
    }
  • Helper utilities used by getDeals: fetchPage (HTTP fetch with Cheerio), absoluteUrl (convert relative URLs), and parsePrice (extract numeric price from text).
    export async function fetchPage(path: string): Promise<CheerioAPI> {
      const url = path.startsWith("http") ? path : `${BASE_URL}${path.startsWith("/") ? "" : "/"}${path}`;
    
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
    
      try {
        const response = await fetch(url, {
          headers: {
            "User-Agent": USER_AGENT,
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7",
          },
          signal: controller.signal,
        });
    
        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText} — ${url}`);
        }
    
        const html = await response.text();
        return cheerio.load(html);
      } finally {
        clearTimeout(timeout);
      }
    }
    
    export function absoluteUrl(path: string | undefined | null): string {
      if (!path) return "";
      if (path.startsWith("http")) return path;
      return `${BASE_URL}${path.startsWith("/") ? "" : "/"}${path}`;
    }
    
    export function parsePrice(text: string | undefined | null): number | null {
      if (!text) return null;
      const cleaned = text.replace(/[R$\s.]/g, "").replace(",", ".");
      const num = parseFloat(cleaned);
      return isNaN(num) ? null : num;
    }

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/leosebben/mcp-meupc'

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