list_community_builds
Browse community PC builds from meupc.net with title, price, and components. Sort builds by newest, best, or best recent.
Instructions
Builds de PC compartilhadas pela comunidade do meupc.net, com título, preço e componentes
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Ordenação das builds ('melhores-recentes', 'melhores', 'novas') | melhores-recentes |
| page | No | Número da página |
Implementation Reference
- src/tools/list-community-builds.ts:14-59 (handler)The actual handler function that scrapes community builds from meupc.net. It fetches the /builds-comunidade page, parses each card for title, author, price, likes, and components, and returns JSON.
export async function listCommunityBuilds(params: ListCommunityBuildsParams): Promise<string> { const { sort, page } = params; const url = `/builds-comunidade?ordem=${sort}&page=${page}`; const root = await fetchPage(url); const results: BuildSummary[] = []; root.querySelectorAll("article.card.is-fullheight").forEach(card => { const titleEl = card.querySelector(".card-content h3.title a"); const title = titleEl?.text.trim() ?? ""; if (!title) return; const buildUrl = titleEl?.getAttribute("href") ?? ""; // Autor const author = card.querySelector(".card-content p.by a.has-text-weight-semibold")?.text.trim() || null; // Preço total const priceText = card.querySelector(".card-content a.preco")?.text.trim() ?? ""; const totalPrice = parsePrice(priceText); // Curtidas const likesAttr = card.querySelector("footer a.js-like-button")?.getAttribute("data-total-likes"); const likesText = card.querySelector("footer span.js-like-total")?.text.trim() ?? ""; const likes = likesAttr ? parseInt(likesAttr, 10) : (likesText ? parseInt(likesText, 10) : null); // Componentes principais (lista no card) const components: string[] = []; card.querySelectorAll(".card-content div.content.is-small ul li").forEach(li => { const comp = li.text.trim(); if (comp) components.push(comp); }); results.push({ title, author, totalPrice, likes: isNaN(likes as number) ? null : likes, url: absoluteUrl(buildUrl), components, }); }); return JSON.stringify(results, null, 2); } - Zod schema defining input parameters: sort (enum of 'melhores-recentes', 'melhores', 'novas') and page (positive int, default 1).
export const listCommunityBuildsSchema = z.object({ sort: z.enum(SORT_OPTIONS).default("melhores-recentes").describe("Ordenação das builds ('melhores-recentes', 'melhores', 'novas')"), page: z.number().int().positive().default(1).describe("Número da página"), }); - src/index.ts:52-59 (registration)Registration of the tool with the MCP server under the name 'list_community_builds', with schema and handler.
server.tool( "list_community_builds", "Builds de PC compartilhadas pela comunidade do meupc.net, com título, preço e componentes", listCommunityBuildsSchema.shape, async (params) => ({ content: [{ type: "text", text: await listCommunityBuilds(params) }], }) ); - src/scraper.ts:37-48 (helper)Helper function absoluteUrl used to convert relative build URLs to absolute URLs.
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; } - src/scraper.ts:43-48 (helper)Helper function parsePrice used to parse price strings into numbers.
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; }