get_build_details
Retrieve detailed PC build information including components, prices, compatibility checks, and estimated power consumption for specific build IDs from meupc.net.
Instructions
Detalhes de uma build específica: lista completa de componentes, preços, compatibilidade e consumo estimado
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| build_id | Yes | ID da build (ex: 'oI7mI7', extraído da URL /build/{id}) |
Implementation Reference
- src/tools/get-build-details.ts:11-99 (handler)Main handler function getBuildDetails that fetches and parses build details from meupc.net. It scrapes the build page to extract title, author, components, prices, compatibility notes, consumption, and totals, then returns a JSON string with all the build information.export async function getBuildDetails(params: GetBuildDetailsParams): Promise<string> { const { build_id } = params; const $ = await fetchPage(`/build/${build_id}`); // Título — pode ser genérico ("PC montado (Build)") ou customizado const title = $("h1.title").first().text().trim() || "Build"; // Autor — buscar no conteúdo da página const authorEl = $("p.by a.has-text-weight-semibold, a[href*='/perfil/']").first(); const author = authorEl.text().trim() || null; // Compatibilidade / observações const compatNotes: string[] = []; $("article.message div.message-body ul li").each((_, li) => { const note = $(li).text().trim(); if (note) compatNotes.push(note); }); // Consumo estimado const consumption = $("div.consumption strong").text().trim() || null; // Componentes da build — iterar por <tr> individual (não por <tbody>) // pois múltiplos itens do mesmo tipo (ex: 2 pentes de RAM) ficam // em <tr> separados dentro do mesmo <tbody> const components: BuildComponent[] = []; $("table.table.is-body-striped tbody:not(.table-responsive-totals) tr").each((_, row) => { const $row = $(row); // Tipo do componente (ex: "Processador", "Placa de vídeo") const type = $row.find("th.table-responsive-title a").first().text().trim() || $row.find("th.table-responsive-title").first().text().trim(); if (!type) return; // Nome do componente (normalizar whitespace interno) const nameEl = $row.find("td.table-responsive-selection a.has-text-strong").first(); const name = nameEl.text().trim().replace(/\s+/g, " "); if (!name) return; const componentUrl = nameEl.attr("href") ?? null; // Preço — tentar PIX (bold) primeiro, depois normal (medium) const pixText = $row.find("td.table-responsive-price a.has-text-weight-bold.has-text-success").first().text().trim(); const normalText = $row.find("td.table-responsive-price a.has-text-weight-medium.has-text-success").first().text().trim(); const price = parsePrice(pixText) ?? parsePrice(normalText); components.push({ type, name, price, url: componentUrl ? absoluteUrl(componentUrl) : null, }); }); // Totais const totalsRows = $("tbody.table-responsive-totals tr"); let totalPrice: number | null = null; let totalPricePix: number | null = null; totalsRows.each((_, row) => { const text = $(row).text(); const priceCell = $(row).find("td.has-text-right").last().text().trim(); if (text.includes("Total no PIX") || text.includes("Total PIX")) { totalPricePix = parsePrice(priceCell); } else if (text.includes("Total") && !text.includes("Desconto")) { totalPrice = parsePrice(priceCell); } }); const result: BuildDetails & { totalPricePix: number | null; compatibility: string[]; consumption: string | null; } = { title, author, totalPrice: totalPricePix ?? totalPrice, likes: null, // Não disponível na página de detalhes components, url: absoluteUrl(`/build/${build_id}`), totalPricePix, compatibility: compatNotes, consumption, }; return JSON.stringify(result, null, 2); }
- src/tools/get-build-details.ts:5-9 (schema)Zod schema definition (getBuildDetailsSchema) for input validation and type inference (GetBuildDetailsParams). Validates that a build_id string is provided as input parameter.export const getBuildDetailsSchema = z.object({ build_id: z.string().describe("ID da build (ex: 'oI7mI7', extraído da URL /build/{id})"), }); export type GetBuildDetailsParams = z.infer<typeof getBuildDetailsSchema>;
- src/index.ts:61-68 (registration)Tool registration for 'get_build_details' with the MCP server. Maps the tool name, description, schema shape, and async handler that calls getBuildDetails and returns the result as text content.server.tool( "get_build_details", "Detalhes de uma build específica: lista completa de componentes, preços, compatibilidade e consumo estimado", getBuildDetailsSchema.shape, async (params) => ({ content: [{ type: "text", text: await getBuildDetails(params) }], }) );
- src/types.ts:46-60 (schema)Type definitions for BuildDetails and BuildComponent interfaces used by get_build_details. BuildDetails contains title, author, totalPrice, likes, components array, and url. BuildComponent represents individual components with type, name, price, and url.export interface BuildDetails { title: string; author: string | null; totalPrice: number | null; likes: number | null; components: BuildComponent[]; url: string; } export interface BuildComponent { type: string; name: string; price: number | null; url: string | null; }
- src/scraper.ts:44-49 (helper)Helper function parsePrice used by getBuildDetails to parse Brazilian currency strings (e.g., 'R$ 1.234,56') into numeric values by removing currency symbols, periods, and replacing comma with decimal point.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; }