jlcpcb-skill-mcp
# jlcpcb-skill-mcp
**English** | [ํ๊ตญ์ด](README.ko.md) | [๐ Docs site](https://hulryung.github.io/jlcpcb-skill-mcp/)
An MCP server + Claude skill that picks JLCPCB/LCSC parts for your KiCad circuit with **assembly cost in mind**.
> ๐ **Docs & install guide (Claude Code / Codex / other MCP clients):** https://hulryung.github.io/jlcpcb-skill-mcp/
Not just search โ it automates part *selection*:
- **Basic > Preferred > Extended tier priority** โ Extended parts carry a $3 loading fee per unique part (Basic is free; Preferred Extended is waived on Economic PCBA)
- **Stock risk checks** โ verifies stock covers 5โ10ร your production need
- **Quantity-tiered pricing** โ costs are computed at the price break your order quantity actually hits
- **KiCad integration** โ parses `.kicad_sch` schematics / BOM CSVs directly and matches lines to LCSC part numbers
- **Package consolidation hints** โ flags the same value scattered across 0603/0805 to save reel changes
Data comes from the public [jlcsearch](https://github.com/tscircuit/jlcsearch) API by tscircuit.
## Demo
One command takes the example ESP32-C3 board from schematic to a costed, tier-aware BOM (live data):

And the same thing inside a **real Claude Code session** โ one natural-language request ("Search for parts and pick the right ones for this board, for a 20-board production run.") drives the skill + MCP tools end to end:

(Also available as MP4: [script demo](docs/demo.mp4) ยท [session demo](docs/demo-claude.mp4). Re-render with `vhs docs/demo.tape` / `vhs docs/demo-claude.tape`.)
## Quick start
```bash
npm install
npm run build
```
This repository ships a `.mcp.json`, so opening this directory in Claude Code registers the server automatically.
The part-selection skill (`.claude/skills/jlcpcb-parts/`) loads alongside it โ ask "pick parts for this circuit" and the skill drives the tools in order, applying the tier/stock/price doctrine.
## Using it in other projects / globally
**Easiest path โ install the plugin** (skill + MCP in one step, no clone or build):
```
/plugin marketplace add hulryung/jlcpcb-skill-mcp
/plugin install jlcpcb-parts@jlcpcb-tools
```
If you installed the plugin, skip the manual registration in 1) and 2) below โ they only matter when developing against a local checkout.
**1) Register the MCP server at user scope** โ applies to every project:
```bash
claude mcp add --scope user jlcpcb-parts -- node /path/to/jlcpcb-skill-mcp/dist/index.js
claude mcp list # confirm "โ Connected"
```
Remove with `claude mcp remove jlcpcb-parts -s user`. (Inside this repo the project-scope `.mcp.json` overlaps with it and prints a duplicate warning; it is the same server, so this is harmless.)
**2) Install the skill globally (personal scope)** โ a symlink, so repo updates propagate automatically:
```bash
ln -sfn /path/to/jlcpcb-skill-mcp/.claude/skills/jlcpcb-parts ~/.claude/skills/jlcpcb-parts
```
**3) Workflow alongside KiCad** โ KiCad itself is not an MCP client, so the integration is "a terminal next to KiCad":
```bash
cd ~/dev/my-board # the project with your .kicad_sch
claude
> Pick parts for this circuit, for a 50-board run.
```
The skill triggers automatically and runs `analyze_kicad` โ `suggest_bom_parts` โ resolves review lines โ estimates cost; ask it to fix LCSC fields/footprints and it edits the schematic for you. **After schematic edits, press F8 in KiCad (Update PCB from Schematic)** to propagate changes to the board. For hierarchical designs, pass the root sheet โ sub-sheets are followed automatically.
**4) Claude Desktop / other MCP clients** โ it is a plain stdio server, so it plugs in anywhere. For Claude Desktop, add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"jlcpcb-parts": {
"command": "node",
"args": ["/path/to/jlcpcb-skill-mcp/dist/index.js"]
}
}
}
```
Fully quit and restart the Desktop app to apply. (Skills are Claude Code-only; Desktop gets the tools.)
**Updating**: `git pull && npm install && npm run build` โ registrations point at `dist/index.js`, so no re-registration is needed.
## Distributing to a team: GitHub, npm, or a remote server
Three ways to share without local paths.
**A) Claude Code plugin (recommended โ ships skill + MCP together)**
This repo is structured as a plugin and its own marketplace (`.claude-plugin/plugin.json` + `marketplace.json`, with a dependency-inclusive single-file bundle `dist-plugin/index.mjs` committed). Teammates need no clone and no build:
```
/plugin marketplace add hulryung/jlcpcb-skill-mcp
/plugin install jlcpcb-parts@jlcpcb-tools
```
Skill and MCP server install together, with update/removal via the `/plugin` menu. After changing server code, run `npm run bundle` and commit the refreshed bundle. Direct single-plugin installs without a marketplace are not supported, hence the included `marketplace.json`.
**B) Publish to npm (MCP only)**
```bash
npm publish # then users run:
claude mcp add jlcpcb-parts -- npx -y jlcpcb-parts-mcp
```
npx caches the package, so it does not reinstall every session. The skill must be distributed separately (option A covers that), so this fits MCP-only consumers. Note `npx github:owner/repo`-style direct GitHub execution is not supported.
**C) Hosted catalog API on Cloudflare D1 (zero download)**
A [Cloudflare Worker](worker/) serves the full in-stock JLCPCB catalog (~693k parts) from D1, so teammates get catalog search without the local DB download โ they just point the local MCP server at the URL. A live instance runs at `https://jlcpcb-parts-api.dkkang7484.workers.dev`:
```bash
claude mcp add --scope user jlcpcb-parts \
-e JLCPCB_API_URL=https://jlcpcb-parts-api.dkkang7484.workers.dev \
-- node /path/to/jlcpcb-skill-mcp/dist/index.js
```
The KiCad file tools still run locally (a remote server can't read your `.kicad_sch`); only the parts data comes from D1. `get_part` proxies live jlcsearch for fresh stock + preferred tier. Deploy your own with `npm run build:d1-db` + the runbook in [worker/README.md](worker/README.md) โ it fits the D1 **free plan** (~330 MB < 500 MB).
## Local parts database (optional)
By default the server queries the live [jlcsearch](https://github.com/tscircuit/jlcsearch) API. You can instead run against a **local copy of the full JLCPCB catalog** โ no rate limits, no dependency on a third-party mirror, and complete results (the live mirror caps some queries at 100 rows).
```bash
npm run db:update # downloads ~830 MB, expands to ~4.9 GB at ~/.cache/jlcpcb-parts/
```
Requires the `unzip` CLI and Node โฅ 22 (built-in `node:sqlite`). The server auto-detects the DB on start and switches to **hybrid mode**: search runs offline over the full catalog, while `get_part` still hits the live API for fresh stock and the preferred-tier flag before you commit to a part. The download is a snapshot (from [bouni/kicad-jlcpcb-tools](https://github.com/bouni/kicad-jlcpcb-tools), rebuilt daily) so stock figures are approximate until that final live check โ always re-verify before ordering.
- Refreshes when older than 7 days (`npm run db:update -- --force` to force).
- `JLCPCB_PARTS_DB=/path/to/parts-fts5.db` overrides the location.
- The catalog DB distinguishes only Basic vs Extended (not Preferred); preferred-extended detection still comes from the live API on `get_part`. Basic detection matches the live data (verified 13/13 on real boards).
## MCP tools (7)
| Tool | Purpose |
|---|---|
| `search_parts` | Free-text search (package / tier / min-stock filters) |
| `search_passives` | Parametric R/C search โ understands `"10k"`, `"4k7"`, `"100nF"` notation |
| `get_part` | Detail lookup by LCSC number (price breaks, attributes) |
| `find_alternatives` | Same-spec substitutes, ranked by tier/stock/price |
| `analyze_kicad` | `.kicad_sch` / BOM CSV โ grouped BOM lines (DNP and LCSC fields honored) |
| `suggest_bom_parts` | Whole-BOM matching + ranking + cost (the core tool) |
| `estimate_assembly_cost` | Component cost + loading fees for a chosen part list |
| `import_part_to_kicad` | Fetch a part's symbol + footprint + 3D model into a KiCad project's libraries, registered and ready to place (via [kicad-lcsc-manager](https://github.com/hulryung/kicad-lcsc-manager) + python3) |
## Example run (real output)
The bundled example board `examples/esp32c3-sensor` (ESP32-C3 + AMS1117 + USB-C + 15 passives), for a 20-board run:
```bash
npm run demo
```
| Refs | Qty | Value | Pkg | LCSC | Tier | Stock | Unit | Status |
|---|---|---|---|---|---|---|---|---|
| J1 | 1 | USB-C | โ | C165948 | extended | 336,394 | $0.16 | preassigned |
| U2 | 1 | AMS1117-3.3 | SOT-223 | C6186 | **basic** | 1,490,681 | $0.15 | preassigned |
| U1 | 1 | ESP32-C3 | QFN-32 | C2838500 | extended | 8,750 | $1.55 | needs_review |
| R1 R2 | 2 | 10k | 0603 | C25804 | **basic** | 37,165,617 | $0.0008 | matched |
| R3 R4 | 2 | 5.1k | 0603 | C23186 | **basic** | 7,571,904 | $0.0009 | matched |
| C1 C2 | 2 | 100nF | 0603 | C14663 | **basic** | 81,299,425 | $0.0022 | matched |
| โฆ | | | | | | | | |
```
Components $39.05 + Loading fees $9.00 (3 extended parts ร $3) = $48.05 ($2.40/board)
needs review: U1 (IC matched via text โ verify footprint), SW1 (switch matched via text)
```
Passives all land on basic-tier parts with millions in stock; low-confidence matches (IC text search, package prefix match) are flagged `needs_review` instead of being silently accepted.
## Selection rules (encoded in the engine + skill)
1. **Hard filters**: out-of-stock dropped; resistance ยฑ0.5% / capacitance ยฑ5% value match; package match (exact for passives, prefix-tolerant for ICs with a review flag); tolerance at least as tight as requested
2. **Scoring**: tier (basic +100 / preferred +60 / extended +0) โ stock adequacy (+25 plus depth bonus) โ price (+15) โ tolerance (+3)
3. **Cost**: the loading fee counts once per unique extended part (no double-charging a part reused across lines)
## Limitations & caveats
- jlcsearch is an **unofficial** mirror of JLCPCB data. Stock and prices are snapshots โ **re-verify with `get_part` right before ordering**.
- Text matching for ICs/connectors is a convenience โ always verify the MPN and datasheet (`needs_review` is that signal).
- Supports KiCad 6โ9 `.kicad_sch` files and common BOM CSV exports.
## Development
```bash
npm test # full test suite (vitest)
npm run demo # live end-to-end demo
node scripts/smoke-mcp.mjs # stdio smoke test of the built server
```
Layout: `src/kicad` (parsers) ยท `src/jlc` (API client) ยท `src/engine` (ranking/cost) ยท `src/tools` (MCP tools) โ module contracts in `CONTRACTS.md`, live API findings in `docs/jlcsearch-api-notes.md`.
## Credits
- Data: [tscircuit/jlcsearch](https://github.com/tscircuit/jlcsearch), upstream data pipeline [yaqwsx/jlcparts](https://github.com/yaqwsx/jlcparts)
- Unofficial project, not affiliated with JLCPCB/LCSC.
MIT License
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: searching (general vs. passives), part lookup, alternatives, BOM suggestion, schematic parsing, KiCad import, and cost estimation. The only slight overlap in cost reporting between suggest_bom_parts and estimate_assembly_cost is clarified by their different roles.
All tool names follow a consistent verb_noun pattern in lowercase snake_case (e.g., search_parts, get_part, find_alternatives, estimate_assembly_cost). The naming is highly regular and predictable.
8 tools is well-scoped for a JLCPCB/PCBA workflow, covering search, lookup, alternatives, BOM handling, KiCad integration, and cost estimation without redundancy or bloat.
The tool set provides end-to-end coverage: analyze a schematic/BOM, suggest parts, search and verify, find alternatives, import to KiCad, and estimate assembly cost. No critical operations are missing for the intended use case.