list_components
Browse PC components by category with pagination and sorting options to compare hardware specifications and prices across Brazilian stores.
Instructions
Lista componentes por categoria com paginação (processadores, placas-video, placas-mae, memorias, armazenamentos, gabinetes, fontes, monitores)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | Categoria de componente (ex: 'processadores', 'placas-video') | |
| page | No | Número da página | |
| sort | No | Ordenação (ex: 'menor-preco', 'maior-preco') |
Implementation Reference
- src/tools/list-components.ts:32-101 (handler)Main handler function listComponents that fetches and returns components from a category. Uses two strategies: extracting JSON from embedded scripts, or falling back to search page scraping. Handles pagination and sorting options.export async function listComponents(params: ListComponentsParams): Promise<string> { const { category, page, sort } = params; // Tentar extrair dados do script embutido na página de categoria const categoryUrl = `/${category}?page=${page}${sort ? `&ordem=${sort}` : ""}`; const $ = await fetchPage(categoryUrl); // Procurar dados JSON nos scripts da página const results = extractFromScripts($, category); if (results.length > 0) { return JSON.stringify(results, null, 2); } // Fallback: usar a página de busca com termo da categoria const categoryTerms: Record<string, string> = { "processadores": "processador", "placas-video": "placa de video", "placas-mae": "placa mae", "memorias": "memoria ram", "armazenamentos": "ssd", "gabinetes": "gabinete", "fontes": "fonte", "monitores": "monitor", "coolers-processador": "cooler processador", "water-coolers": "water cooler", }; const searchTerm = categoryTerms[category] ?? category; const encoded = encodeURIComponent(searchTerm); const $search = await fetchPage(`/pesquisar?q=${encoded}&page=${page}`); const searchResults: ComponentResult[] = []; $search("div.media").each((_, el) => { const $el = $search(el); const name = $el.find("div.media-content a h4").text().trim(); if (!name) return; const url = $el.find("div.media-content > a").attr("href") ?? ""; const image = $el.find("div.media-left figure img").attr("src") ?? null; const addLink = $el.find("a.button.is-link").attr("href") ?? ""; const catMatch = addLink.match(/meupc\.net\/([^/]+)\/add\//); const cat = catMatch ? catMatch[1] : null; const priceText = $el.find("div.media-content > p").filter((_, p) => { return $search(p).text().includes("R$"); }).first().text(); const pixMatch = priceText.match(/R\$\s*([\d.,]+)\s*no PIX/); const normalMatch = priceText.match(/R\$\s*([\d.,]+)/); const priceStr = pixMatch ? pixMatch[1] : normalMatch ? normalMatch[1] : null; const price = parsePrice(priceStr); searchResults.push({ name, category: cat, price, url: absoluteUrl(url), image: image && !image.includes("placeholder") ? absoluteUrl(image) : null, }); }); return JSON.stringify({ note: "Dados obtidos via busca (a listagem por categoria usa renderização client-side)", category, page, results: searchResults, }, null, 2); }
- src/tools/list-components.ts:18-24 (schema)Zod schema defining input parameters for list_components tool: category (enum of valid component categories), page (positive integer, defaults to 1), and optional sort parameter.export const listComponentsSchema = z.object({ category: z.enum(CATEGORIES).describe("Categoria de componente (ex: 'processadores', 'placas-video')"), page: z.number().int().positive().default(1).describe("Número da página"), sort: z.string().optional().describe("Ordenação (ex: 'menor-preco', 'maior-preco')"), }); export type ListComponentsParams = z.infer<typeof listComponentsSchema>;
- src/index.ts:25-32 (registration)MCP server tool registration for 'list_components'. Defines the tool name, description, input schema shape, and handler that executes the listComponents function.server.tool( "list_components", "Lista componentes por categoria com paginação (processadores, placas-video, placas-mae, memorias, armazenamentos, gabinetes, fontes, monitores)", listComponentsSchema.shape, async (params) => ({ content: [{ type: "text", text: await listComponents(params) }], }) );
- src/tools/list-components.ts:103-139 (helper)Helper function extractFromScripts that attempts to extract component data from embedded JSON scripts in the Vue.js-rendered pages. Searches for patterns like window.meupcnetPecas, window.meupcnetData, or var pecas.function extractFromScripts($: ReturnType<typeof import("cheerio").load>, category: string): ComponentResult[] { const results: ComponentResult[] = []; $("script").each((_, script) => { const content = $(script).html() ?? ""; // Tentar encontrar arrays de dados de peças em variáveis window.* const patterns = [ /window\.meupcnetPecas\s*=\s*(\[[\s\S]*?\]);/, /window\.meupcnetData\s*=\s*(\{[\s\S]*?\});/, /var\s+pecas\s*=\s*(\[[\s\S]*?\]);/, ]; for (const pattern of patterns) { const match = content.match(pattern); if (match) { try { const data = JSON.parse(match[1]); const items = Array.isArray(data) ? data : (data.pecas ?? data.items ?? []); for (const item of items) { results.push({ name: item.nome ?? item.name ?? item.title ?? "", category, price: item.preco ?? item.price ?? item.menor_preco ?? null, url: item.url ? absoluteUrl(item.url) : `${BASE_URL}/peca/${item.hash ?? item.id ?? ""}`, image: item.imagem ?? item.image ?? null, }); } } catch { // JSON parse falhou, continuar } } } }); return results; }