EasyEDA MCP

io.github.zzvllvzz由 GitHub 账号 zzvllvzz 发布v0.1.0更新于 Nov 14, 2026

Read and draw EasyEDA Pro schematics and PCBs through a bridge extension, with guarded edits.

已验证STDIO仅桌面开发者工具媒体与设计

概览

AI 生成的概览

通过桥接扩展让助手读取、绘制并导出 EasyEDA 专业版的原理图与 PCB,编辑受保护并可回滚。

可以做什么
  • 检查桥接连接状态、编辑器版本与当前项目或图页
  • 在 EasyEDA 内执行 JavaScript 或单个 API 调用,并检索 API 参考
  • 读取原理图:元件、引脚、导线、网络、检查、重叠与空闲空间
  • 批量绘制原理图,带短路保护、试运行与回滚,并导出 PDF、PNG、SVG、网表或 BOM
  • 读取电路板:元件、焊盘、走线、过孔、铺铜、网络、未布线连接与 DRC
  • 批量绘制电路板并以 DRC 把关,执行从原理图导入、重新铺铜、自动布线等操作,导出 Gerber、坐标文件、STEP 等格式
适用场景
当你使用 EasyEDA 专业版桌面客户端,希望助手检查设计、批量生成或修改原理图与电路板内容,或产出制造与文档导出文件时适用。受保护的绘制工具和试运行模式适合那些一旦出现短路网络或新 DRC 错误就必须撤销的编辑。
运行要求
EasyEDA 专业版桌面客户端 3.x,并已导入桥接扩展且允许外部交互;Node.js 20 或更高版本;可运行 stdio 服务器的 MCP 客户端,例如 Claude Code。扩展连接本地端口(默认 49731)。可选环境变量 EASYEDA_MCP_PORT、EASYEDA_MCP_OUT 和 EASYEDA_MCP_ORIGINS。
安装前请注意
扩展会执行服务器发来的任意代码,拥有编辑器 API 和你 EasyEDA 账户的完整权限,eda_exec 可调用任何编辑器函数,包括下单类函数。EasyEDA 在编辑后数秒自动保存到云端,且 API 没有撤销功能,风险操作应使用试运行模式或临时项目。已删除的元件、文本和图形无法恢复。仅报告在 Windows 上的 EasyEDA 专业版 3.2.209 测试过。

安装

在 SourceWeft 中

  1. 打开 控制台中的 EasyEDA MCP,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

easyeda-mcp

An MCP server that lets Claude Code (or any MCP client) read and draw schematics and PCBs in EasyEDA Pro.

A tiny extension inside the editor does one thing: it runs the JavaScript the server sends, with access to the eda API, and returns the result. All tool logic lives in the server, so fixes and new tools never require reinstalling the extension.

Edits are guarded: sch_draw and pcb_draw apply a whole batch of operations or nothing, and take the change back by themselves when it shorts two named nets on the schematic or adds a design rule error on the board.

Requirements

  • EasyEDA Pro desktop client 3.x (tested on 3.2.209 for Windows).
  • Node.js 20 or newer on PATH.
  • Claude Code, or another MCP client that runs stdio servers.

Install

1. The bridge extension in EasyEDA Pro

  1. Download easyeda-mcp-bridge.eext from the latest release.
  2. In EasyEDA Pro open the extension manager and import the file.
  3. Allow the extension External Interaction. It needs it to reach the local server.
  4. Restart EasyEDA. The extension starts only when the editor starts.

The extension connects to ws://127.0.0.1:49731 by itself and reconnects when the link drops. The editor gets an MCP menu with Reconnect and Status.

2. The server in Claude Code

As a plugin, in a Claude Code session:

/plugin install easyeda --marketplace zzvllvzz/easyeda-mcp

On Claude Code older than 2.1.275, add the marketplace first:

/plugin marketplace add zzvllvzz/easyeda-mcp/plugin install easyeda@easyeda-mcp

Then run /reload-plugins or start a new session.

Or from npm, without the plugin:

sh
# macOS, Linuxclaude mcp add easyeda -s user -- npx -y easyeda-pro-mcp# Windowsclaude mcp add easyeda -s user -- cmd /c npx -y easyeda-pro-mcp

Or from source:

sh
git clone https://github.com/zzvllvzz/easyeda-mcpcd easyeda-mcpnpm installclaude mcp add easyeda -s user -- node /absolute/path/to/easyeda-mcp/server/index.mjs

Other MCP clients: run npx -y easyeda-pro-mcp as a stdio server.

3. Check

With EasyEDA open, ask Claude to check the EasyEDA connection. eda_status should answer connected with the editor and extension versions and the active project.

Tools

  • eda_status: is the editor connected, versions, active project and sheet, state of the bridge.
  • eda_exec: run JS inside EasyEDA (eda, helpers h, args, console, store).
  • eda_call: call one API method by its path.
  • eda_api: search the API reference built from @jlceda/pro-api-types.
  • sch_read: read a sheet: summary, parts with pins, wires, nets, check (check), overlaps (overlaps), free room (free).
  • sch_draw: a batch of operations on the sheet as one guarded change (see below).
  • sch_export: PDF, PNG, SVG, netlist, BOM to a file.
  • lib_search: find parts in the library by words or LCSC numbers.
  • pcb_read: the board: info, parts with pads, tracks, vias, pours and regions, nets, unrouted connections, DRC.
  • pcb_draw: a batch of operations on the board as one change guarded by DRC.
  • pcb_do: open a board, import changes from the schematic, refill pours, autoroute, remove routing.
  • pcb_export: Gerber, pick and place, BOM, STEP/OBJ, DXF, DSN, IPC-356, IPC-2581, ODB++, PDF and more.

The helpers h live in server/helpers.js and are read again on every call, so the file can be edited while the server runs.

Guard, trial run and rollback

sch_draw and pcb_draw apply the list of operations as a whole or not at all.

On the schematic a netlist is taken before and after the change. If nets with different names given by a person merged into one, that is a short: the change is taken back and the report names the nets and the pins. A change in which an operation failed, or an expect ({NET: [pins]}) did not hold, is taken back the same way. After a rollback the netlist is compared with the original and the report says restored: true. allowShorts permits an intended merge. The report always shows what happened to the nets: what got connected, what dropped off, what split, what was renamed.

On the board DRC runs before and after the change. A new error other than a connection that is not routed yet (clearance, short, entering a keep-out) takes the change back. Pours are refilled before the check. allowErrors keeps a change with errors.

trial: true performs the change in the editor, shows the report and takes it back in any case. A rollback restores moved parts, properties, the no-connect mark, wire names and shapes, deleted wires, tracks and vias. Deleted parts, texts and shapes cannot be restored, so a trial run that deletes parts is refused up front.

The guard forbids nothing in advance by geometry: EasyEDA itself decides, and the netlist or DRC judges the result. It gives no false refusals.

Security

The extension runs whatever code the local server sends, with full access to the editor API and your EasyEDA account. Keep that in mind:

  • The server listens on 127.0.0.1 only. Browsers can open WebSockets to localhost from any site, so the server refuses connections that carry a browser Origin other than EasyEDA's own (https://*.easyeda.com, https://*.lceda.cn). More origins can be allowed with EASYEDA_MCP_ORIGINS, comma separated. Local programs (other sessions of this server, scripts/run.mjs) send no Origin and are accepted, as with any local developer tool.
  • eda_exec can call any editor function, including the ordering ones (placePcbOrder, placeComponentsOrder and similar). The tool description tells the model never to call them.
  • EasyEDA saves changes to the cloud by itself a few seconds after an edit, and the API has no undo. Try risky edits with trial: true or on a scratch sheet or project.

How it works

  • extension/dist/index.js: the extension, written by hand without a bundler.
  • server/link.mjs: the link to the editor. The first server started owns the port; servers of other Claude sessions go through it. If the first one exits, the next one takes the port.
  • server/index.mjs: MCP over stdio and the tools. Large answers are saved to ~/.easyeda-mcp/out/, the reply carries the beginning and the path.
  • server/api-index.mjs: parses the API typings for search.

Environment variables: EASYEDA_MCP_PORT (the port in the extension has to change too), EASYEDA_MCP_OUT, EASYEDA_MCP_ORIGINS.

Development

  • npm test runs real server processes and the real extension code against a fake eda (test/fake-eda.mjs). It does not check the behaviour of a live EasyEDA.
  • npm run build:ext packs extension/ into easyeda-mcp-bridge.eext (needs Node 20.15 or 22.2 and newer).
  • node scripts/run.mjs draw <ops.json> [--trial] [--no-guard] and node scripts/run.mjs exec <code.js> [args.json] run sch_draw operations or code from a file through the hub of a running server. Useful for generators with hundreds of operations.

Updating the extension without the import dialog: if EasyEDA runs with a debugging port (easyeda-pro.exe --remote-debugging-port=9333 --remote-allow-origins=*), a new build can be put into its extension storage directly: npm run build:ext, then node scripts/push-ext.mjs, then restart EasyEDA. The very first install still goes through the import dialog.

Tested on a live EasyEDA Pro 3.2.209

Schematic: reading, every sch_draw operation, short protection, trial run and rollback (six scenarios, the sheet came back identical), check, overlaps, free room search, export pdf/png/svg/netlist/bom/view. Load: 260 operations in one call (120 parts, 130 wires, 10 ground symbols) with a check of 130 nets took 100 seconds with the window hidden.

Board (in a scratch project): import from the schematic, moving parts, tracks, vias, a pour with fill, a keep-out region, text, outline, DRC, protection against shorted tracks and entering a keep-out, autorouting, export gerber/pnp/bom/step/dxf/dsn/ipc356/odb/altium/pdf/netlist.

Link: works with the window minimized, recovers after a dropped socket and after the computer sleeps.

Not tested: multilayer boards and blind vias, net classes and differential pairs (available through the raw API), boards and sheets with hundreds of parts, the web editor, macOS and Linux.

Known limitations

  • A modal dialog in the editor blocks the API call that opened it, and the bridge does not see it: the call waits until its timeout. Example: "this device has been updated, update in the project?" when placing a part whose symbol changed after its first use in the project. Press the button in the editor, or find the dialog in top.document from eda_exec and click it there.
  • No tools for creating sheets, changing the sheet format or editing library symbols. The raw API is available through eda_exec.
  • sch_draw takes its operations inline only; for long lists use scripts/run.mjs. trial and the part op do not return pin coordinates, and the set op cannot mark a part as not placed (DNP).
  • lib_search cuts descriptions at about 120 characters.

Editor quirks the helpers work around

  • The list of wires on a sheet (getAll, getAllPrimitiveId) lags about a second behind wire creation, get(ids) sees them at once. h.draw waits for the update; after the raw API call h.settle(ids).
  • sch_PrimitiveComponent.create stores rotation 90 as 270 and the other way round; modify is correct.
  • sch_PrimitivePin.modify without y flips the sign of the pin's y and the pin flies off the part. Pass the current y.
  • Right after a netlist is generated the editor rejects edits: modify throws cmdKey, a wire create throws create failed!, delete silently returns false. A retry a moment later succeeds.
  • Connectivity lags about a second behind a wire deletion: a netlist taken at once still shows the old nets.
  • A new wire merges with every wire whose end it touches; create returns the old wire's id.
  • A power symbol or a port cannot be modified, only deleted and created again. Rotation 90 is stored as 270 on creation for them too. A symbol right on a pin end hangs on a zero-length wire that cannot be created by hand: after moving the part away and back the symbol is attached anew.
  • Every operation on a sheet gets slower as the sheet fills up; creating a part takes 0.5 to 0.7 s, so parts are placed in batches of eight.
  • sch_Drc.check returns only the number of findings per severity; the list exists only in the editor panel.
  • Board: pcb_Primitive.getPrimitiveTypeByPrimitiveId always answers undefined; a pour is refilled with the object's rebuildCopperRegion(); importChanges() only opens a confirmation dialog, h.pcb.import presses its button; getPdfFile without content settings never answers; dmt_Project.deleteProject returns false and does not delete the project.
  • Generating a netlist numbers the "R?" parts across the whole project. The API has no separate call for annotation.
  • getPdfFile does not exist in the editor, getPngFile and getSvgFile never resolve. getExportDocumentFile does all of it.
  • The extension script may run twice in a page, so there is one runtime per page (globalThis.__easyedaMcpBridge__, info() shows its state).
  • In a minimized or hidden window page timers fire once a second, and after the fifth in a chain once a minute (measured: twelve pauses of 0.1 s took 3.7 minutes). So the connection watchdog and the helpers' pauses (h.sleep, h.limit, h.settle) run on a timer in a worker: thirty such pauses take 3.3 s. The editor's own timers suffered the same way (netlist 53 s instead of 2 s, creating a part 24 s), so while the window is hidden the helpers move the page's setTimeout and setInterval onto the same worker. With a visible window the timers are native. Turn it off with h.pageTimers(false).

License

MIT. The API reference is built from @jlceda/pro-api-types (Apache-2.0), installed as a dependency.

来源:README.md,提交 a2e1756

工具

12

eda_status

Check the bridge: is EasyEDA Pro connected, which editor/extension version, and what project/document/page is active.

输入参数waitMs

eda_exec

Run JavaScript inside EasyEDA Pro and get the returned value. The code is the body of an async function with `eda` (the EasyEDA extension API), `h` (helpers), `args` (your JSON), `console` (captured) and `store` (object that persists between calls). Use `return` for the result. Do many operations in ONE call with loops instead of many calls. EasyEDA primitives are returned as plain objects built from their getState_* getters; File/Blob results are saved to disk and returned as a path. Nothing is guarded or confirmed: read back what you changed. Schematic y axis points up. Helpers available as `h` inside eda_exec code (all async unless noted): h.ctx() current project/document/schematic/page | h.pages() | h.openPage(uuidOrName) h.parts({pins?, des?, region?:[x1,y1,x2,y2], type?, allPages?}) compact components; h.part("U1") one component with pins h.wires(net?) | h.snapshot({region?, pins?}) parts+flags+wires of the page h.nets() {net:["U1.3",...]} from the native PADS netlist (all pages) | h.net("GND" | "U1.3") | h.checkNets({NET:["U1.3","R2.1"]}) h.lcsc("C1234" | [..]) -> {found:{id:{uuid,libraryUuid}}, missing} h.draw(ops, {trial?, expect?:{NET:[pins]}, allowShorts?, rollback?, guard?, keepGoing?, verbose?}) one change, all or nothing (see sch_draw) ops: {op:"wire",line:[x1,y1,x2,y2,..],net?} {op:"part",lcsc|device,x,y,rot?,des?} {op:"flag",kind:"Ground"|"Power",net,x,y,rot?} {op:"port",dir:"IN"|"OUT"|"BI",net,x,y,rot?} {op:"move",part,x?,y?,rot?} {op:"set",part,props} {op:"nc",pin:"U1.3"} {op:"unname",wire} {op:"rewire",wire,line} {op:"delete",wires?,parts?,others?} {op:"text",x,y,text,size?,rot?} {op:"rect",x,y,w,h} {op:"circle",x,y,r} {op:"line",line:[..]} {op:"attr",part,key:"Designator"|"Name",x?,y?,rot?,visible?} h.netDiff(before, after) what changed between two h.nets() results (shorts, joined, dropped, split, renamed, connected; sync) h.erc({strict?, ui?}) floating pins, single-pin nets, unnumbered and duplicate designators + EasyEDA's ow

输入参数argscode必填saveTomaxCharstimeoutMs

eda_call

Call one EasyEDA API method by path, e.g. method 'sch_PrimitiveWire.getAll' with args ['GND']. Shortcut for simple reads and single writes; for anything with loops use eda_exec. Look up signatures with eda_api.

输入参数argsmethod必填saveTomaxCharstimeoutMs

eda_api

Look up the EasyEDA Pro extension API (offline, from the official typings; doc comments are in Chinese). `query`: keyword search over method names and docs. `name`: full listing of a class/eda object (sch_PrimitiveWire), an interface, enum or type, or one method with remarks and example (sch_PrimitiveWire.modify). No arguments: overview of all eda.* objects.

输入参数namelimitqueryexamples

sch_read

Read the active schematic page compactly. what: 'summary' (counts, designators, net names of wires), 'parts' (components with pin coordinates), 'wires', 'snapshot' (parts+flags+wires), 'nets' (whole-schematic netlist {net: pins}), 'net' (one net by name or by pin like 'U1.3', needs `net`), 'check' (floating pins, single-pin nets, unnumbered or duplicate designators, EasyEDA's own rule check counts), 'overlaps' (parts, labels and wires lying on each other), 'free' (room for a block of `size` [w,h]: rectangles touching nothing), 'boxes' (the rectangle every object takes). Filter with `des` (designators) or `region` [x1,y1,x2,y2]. Pin x,y is the outer end where a wire attaches.

输入参数desnetpinssizewhatcountregionsaveTomaxChars

sch_draw

Apply a list of drawing operations to the active schematic page as ONE change: afterwards either all of it is on the page or none of it. The netlist is read before and after (guard): nets with different names that became one net are a short, and a short takes the whole change back, as does a failed op or an `expect` that does not hold; the report says what happened to the nets (connected, joined, dropped, split, renamed) and `restored:true` confirms that the netlist is back to what it was. trial:true does the change, reports, and takes it back in any case (a dry run on the real editor). ops: {op:'wire',line:[x1,y1,x2,y2,...],net?} | {op:'part',lcsc:'C1234'|device:{libraryUuid,uuid},x,y,rot?,mirror?,des?} | {op:'flag',kind:'Ground'|'Power'|'AnalogGround'|'ProtectGround',net,x,y,rot?} | {op:'port',dir:'IN'|'OUT'|'BI',net,x,y,rot?} | {op:'move',part:'R1',x?,y?,rot?,mirror?} | {op:'set',part,props:{designator?,name?}} | {op:'nc',pin:'U1.3'} | {op:'unname',wire:id} | {op:'rewire',wire:id,line} | {op:'delete',wires?:[ids],parts?:[ids|designators],others?:[ids of texts/shapes]} | {op:'text',x,y,text,size?,rot?,color?} | {op:'rect',x,y,w,h} (x,y top left) | {op:'circle',x,y,r} | {op:'line',line:[...]} (drawing line, not a wire) | {op:'attr',part,key:'Designator'|'Name',x?,y?,rot?,visible?,value?} (move or edit a label of a part). Notes: y points up; a wire with `net` gets a visible label; EasyEDA merges a new wire with every wire whose end it touches (reported as merged, the old wire keeps its id); pins touching end to end without a wire are not connected; parts placed without `des` are numbered by EasyEDA (unique across all pages); the netlist also numbers any other 'R?' part of the project; deleted parts cannot be put back by a rollback.

输入参数ops必填guardtrialexpectverboserollbackkeepGoingtimeoutMsallowShorts

sch_export

Export from the active schematic to a file and return its path: pdf (look at the real drawing; open the path with the Read tool), png, svg, netlist (PADS text), bom (csv), view (image of what the canvas currently shows; may be stale).

输入参数pathformat必填optionstimeoutMs

pcb_read

Read the active PCB (open one with pcb_do action:'open'). what: 'info' (layers, rule set, outline size, counts), 'parts' (components; pads:true adds pad coordinates and nets), 'tracks', 'vias', 'shapes' (polylines, pours, regions, fills, texts), 'nets' (pads, track length, tracks and vias per net; `net` for one), 'unrouted' (pads still waiting for a connection), 'drc' (design rule check with the list of errors). Coordinates are in mil with y up; unit:'mm' switches to millimetres.

输入参数desmaxnetpadsunitwhatlayersaveTomaxChars

pcb_draw

Apply a list of operations to the active PCB as ONE change. The design rule check runs before and after (guard): a new error other than a not-yet-routed connection (clearance, short, overlap with a keep-out) takes the whole change back, as does a failed op; pours are refilled before judging. trial:true reports and takes it back in any case. Coordinates in mil, y up (unit:'mm' for millimetres); layer by number or name (top, bottom, topsilk, bottomsilk, outline, document, inner1...). ops: {op:'track',net,layer,points:[x1,y1,x2,y2,...],width?} | {op:'via',net,x,y,hole?,dia?} | {op:'move',part:'R1',x?,y?,rot?,layer?} | {op:'place',lcsc|device|footprint,x,y,layer?,rot?,des?} | {op:'set',part,props} | {op:'outline',rect:[x,y,w,h]|points:[...]|circle:[x,y,r]} | {op:'pour',net,layer,rect|points,name?,priority?} | {op:'region',layer,rect|points,rules?} (keep-out) | {op:'fill',layer,rect|points|circle,net?} | {op:'text',layer,x,y,text,size?,width?,rot?} | {op:'line',layer,points,width?} (silkscreen or document line) | {op:'delete',ids:[...]}. A rectangle starts at its top left corner. Components normally come from the schematic (pcb_do action:'import'); deleted shapes, texts and components cannot be put back by a rollback, tracks and vias can.

输入参数ops必填unitguardtrialrebuildverboserollbackkeepGoingtimeoutMsallowErrors

pcb_do

Whole-board actions. action: 'open' (open a PCB of the project by `name` or uuid, the first one by default), 'import' (bring the schematic's changes onto the board; lists the changes and applies them, apply:false only lists), 'rebuild' (refill all pours), 'autoroute' (EasyEDA's own router; `props` like {RoutingNets:['A','B'], layers:[1,2], ignoreNets:[...]}), 'unroute' (delete all tracks and vias of `net`, or of every net when none is given).

输入参数netnameapplypropsaction必填timeoutMs

pcb_export

Export from the active PCB to a file and return its path: gerber (zip for fabrication), pnp (pick and place csv), bom, netlist, step, obj (3D), dxf, dsn (for external routers), ipc356, ipc2581, odb, testpoints, info, altium, pads, view (picture of what the canvas shows). Nothing is ordered: EasyEDA's ordering functions are never called.

输入参数pathformat必填optionstimeoutMs

版本历史

1
  1. v0.1.0最新Nov 14, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分