partscout #
mcp server for pricing computer hardware on ebay — built with FastMCP for TypeScript.
written to answer one question honestly: should i buy this used?
why #
shopping for homelab gear means bouncing between listings trying to work out whether $300 for a used rack is a deal or a ripoff. that is a distribution question, not a lookup — so these tools return distributions.
tools #
| tool | question it answers |
|---|---|
search_gear |
filtered listing candidates, with seller and shipping context |
get_listing |
refresh a candidate’s price and API stock status by item ID |
price_snapshot |
what does this go for (low / p25 / median / p75 / high) |
new_vs_used |
should i buy used, and how much does it actually save |
suggest_categories |
which ebay category is this, when a price looks wrong |
caveats worth knowing #
- these are asking prices, not sold prices. the ebay Browse API exposes active listings only; sold data lives behind the restricted Marketplace Insights API. title filtering removes common false matches, but inspect candidate details before relying on either the minimum or median.
- GPU searches check titles, not just categories. RTX model/variant mismatches,
empty boxes, loose coolers, waterblocks, NVLink bridges, missing-core cards,
damaged/untested cards, and mobile eGPUs are excluded from desktop GPU searches.
strict_gpu_model,include_accessories, andinclude_for_partsallow broader searches. This is a title heuristic, not a guarantee of condition or authenticity. Filtering scans at most five pages to fill the requested result limit. - search results can be stale. Call
get_listingwith a result'sitem_idbefore recommending it. It refreshes the eBay item API's availability and price;unknownmeans unverified, not in stock. Shipping quotes may lack destination context; null is unknown, not free. Seller feedback count accompanies percentage. - snapshots use USD fixed-price listings only, excluding shipping and tax. They describe the filtered best-match sample, not the entire market, past prices, warranty eligibility, or a recommendation to buy. Open-box remains in “new.”
- searches are category-scoped by default. keyword search alone is not
enough: "Synology DS923+" unscoped returns ram upgrades and power bricks and
prices them as if they were the NAS. every search is scoped to ebay's
suggested category; pass
auto_category: falseto opt out, or pincategory_idwhen the guess is wrong.suggest_categoriesshows the guesses. - ebay's condition buckets are broader than they sound.
NEWalso returns "Open box" (kept — a real listing at a real price).USEDalso returns "For parts or not working" (dropped by default — a dead card is not a data point about what a working one costs). refurbished is in neither bucket. - ebay often asks above retail for current-production goods. it is the right tool for used and discontinued hardware, the wrong one for anything you can still buy new from a retailer.
setup #
requires Node.js 22 or newer. register an application at
developer.ebay.com and put the keys in the
environment or a local .env:
EBAY_CLIENT_ID=your-app-id
EBAY_CLIENT_SECRET=your-cert-id
# optional
EBAY_MARKETPLACE_ID=EBAY_US
EBAY_BASE_URL=https://api.ebay.com # or https://api.sandbox.ebay.com
the Browse API uses an application token (client credentials), so there is no user login step — it reads public listings and never acts on an account.
run #
npm install
npm run build
npm start # stdio, from the built package
npm run dev # interactive FastMCP development client
register the source checkout with Claude Code:
claude mcp add partscout -- npx --yes tsx /path/to/partscout/src/server.ts
or install the package and use its partscout-mcp executable.
use as a library #
import { Ebay } from "partscout";
const ebay = new Ebay();
const result = await ebay.newVsUsed("Synology DS925+");
console.log(result.verdict);
development #
npm run check
unit tests mock the ebay transport, so they need no credentials. live regression
tests run automatically when EBAY_CLIENT_ID and EBAY_CLIENT_SECRET are set.