From 942db02efe92ee1b66299b837088db5a1e1e1166 Mon Sep 17 00:00:00 2001 From: Hasan Ozalp Date: Wed, 21 Oct 2026 20:04:19 -0700 Subject: [PATCH] feat: add EasyGerber plugin --- .factory-plugin/marketplace.json | 6 ++ README.md | 8 ++ .../easygerber/.factory-plugin/plugin.json | 28 ++++++ plugins/easygerber/LICENSE | 24 +++++ plugins/easygerber/README.md | 59 ++++++++++++ plugins/easygerber/assets/icon.svg | 5 + plugins/easygerber/assets/logo.svg | 5 + plugins/easygerber/mcp.json | 8 ++ plugins/easygerber/skills/easygerber/SKILL.md | 28 ++++++ .../skills/easygerber/references/workflow.md | 91 +++++++++++++++++++ skills/easygerber | 1 + 11 files changed, 263 insertions(+) create mode 100644 plugins/easygerber/.factory-plugin/plugin.json create mode 100644 plugins/easygerber/LICENSE create mode 100644 plugins/easygerber/README.md create mode 100644 plugins/easygerber/assets/icon.svg create mode 100644 plugins/easygerber/assets/logo.svg create mode 100644 plugins/easygerber/mcp.json create mode 100644 plugins/easygerber/skills/easygerber/SKILL.md create mode 100644 plugins/easygerber/skills/easygerber/references/workflow.md create mode 120000 skills/easygerber diff --git a/.factory-plugin/marketplace.json b/.factory-plugin/marketplace.json index 4282159..3528025 100644 --- a/.factory-plugin/marketplace.json +++ b/.factory-plugin/marketplace.json @@ -53,6 +53,12 @@ "description": "Pull request lifecycle skills: create PRs with consistent conventions and follow up on them until merge-ready", "source": "./plugins/code-review", "category": "productivity" + }, + { + "name": "easygerber", + "description": "AI PCB design, layout, and routing", + "source": "./plugins/easygerber", + "homepage": "https://easygerber.com/agents" } ] } diff --git a/README.md b/README.md index 62f7f3f..dcba4f3 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,14 @@ Skills for continuous learning and improvement. Autonomous experiment loop for optimization research. Try an idea, measure it, keep what works, discard what doesn't, repeat. Works standalone or as a mission worker. +### easygerber + +AI PCB design, layout, and routing + +**Skills:** `easygerber` — board workflow through EasyGerber’s hosted MCP service. + +See [plugins/easygerber/README.md](plugins/easygerber/README.md) for setup and account access. + ## Plugin Structure Each plugin follows the Factory plugin format: diff --git a/plugins/easygerber/.factory-plugin/plugin.json b/plugins/easygerber/.factory-plugin/plugin.json new file mode 100644 index 0000000..8d46282 --- /dev/null +++ b/plugins/easygerber/.factory-plugin/plugin.json @@ -0,0 +1,28 @@ +{ + "name": "easygerber", + "displayName": "EasyGerber", + "version": "0.3.4", + "description": "AI PCB design, layout, and routing", + "author": { + "name": "EasyGerber", + "url": "https://easygerber.com" + }, + "homepage": "https://easygerber.com/agents", + "license": "MIT", + "keywords": [ + "easygerber", + "ai pcb design", + "pcb design", + "circuit board design", + "printed circuit board design", + "circuit design", + "schematic design", + "pcb layout", + "automatic pcb routing", + "electronic component search", + "3d pcb preview", + "gerber export", + "pcb manufacturing files", + "bill of materials" + ] +} diff --git a/plugins/easygerber/LICENSE b/plugins/easygerber/LICENSE new file mode 100644 index 0000000..45d8c54 --- /dev/null +++ b/plugins/easygerber/LICENSE @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2026 EasyGerber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +This license applies only to this integration package. It does not grant +rights to EasyGerber's hosted service, component catalog, or private engines. diff --git a/plugins/easygerber/README.md b/plugins/easygerber/README.md new file mode 100644 index 0000000..42d5114 --- /dev/null +++ b/plugins/easygerber/README.md @@ -0,0 +1,59 @@ +# EasyGerber for Factory Droid + +![EasyGerber](assets/logo.svg) + +AI PCB design, layout, and routing. + +Design circuit boards with AI, from your first idea to the files your manufacturer needs. Describe what you want to build in everyday language, or start with the pin assignments in your firmware. + +Choose from over one million electronic components in EasyGerber’s catalog, including LEDs, sensors, connectors, and microcontrollers. Build with real catalog parts, their footprints, and available 3D models—from a simple LED circuit to a custom electronics project. + +Create and edit schematics, generate PCB layouts with automatic component placement and routing, and refine your design through conversation. Adjust board settings, explore copper layers, inspect your board in interactive 3D, and check for blocking layout issues before exporting. + +Download Gerber files, drill files, a bill of materials (BOM), component placement files, and an editable EasyGerber file to continue working on your design. + +Start with one guest board without signing up through `https://www.easygerber.com/api/mcp`. No account authorization is needed for guest access. When you sign in to keep or continue working on the guest board, the agent saves it to your account after consent. If you connect through client settings for that purpose, resume the task so the agent can finish saving it; the sign-in callback alone does not transfer the board. Signing in solely to delete an account board or submit feedback does not authorize claiming a guest board. + +## Install the plugin + +This Factory plugin wraps the published EasyGerber 0.3.4 integration at [immutable source revision `fb61fbb68621d15ecb4861fe849346d733cc8f76`](https://github.com/EasyGerber/easygerber-agent-plugin/tree/fb61fbb68621d15ecb4861fe849346d733cc8f76/claude). Its manifest, MCP configuration, skill, workflow reference, artwork, and license retain the published file contents; only the two native configuration paths are renamed for Factory. The npm installer configures Codex only and is not needed here. + +Requires the Factory Droid CLI with plugin support and an internet connection to EasyGerber. From a checkout containing this contribution: + +```sh +droid plugin marketplace add . +droid plugin install easygerber@factory-plugins --scope user +``` + +After this contribution is accepted into the official marketplace: + +```sh +droid plugin marketplace add https://github.com/Factory-AI/factory-plugins +droid plugin install easygerber@factory-plugins --scope user +``` + +Restart Droid after installation. Use `/plugins` to inspect the EasyGerber plugin and `/mcp` to inspect its connection or authorize account access when needed. Keep normal tool approvals enabled. Factory model access has its own account and plan requirements. + +For a connection check without board changes, ask: “Read the EasyGerber skill and report the available EasyGerber tool names. Do not call a tool, create a guest session or board, authenticate, or send feedback.” Native installation, guest workflows, and account authorization are separate checks; this package does not claim that an untested flow passed. + +Try: “Create a small 3.3 V LED board, show a preview, and export the manufacturing files and EasyGerber file.” Use an authorized account if connected; otherwise the service supports one guest board per session. The guest board has no automatic expiry, while generated download links expire after fifteen minutes. The private guest viewer link grants access to the design; keep it private. Signing in to continue working on that guest board includes saving it to your personal account. The agent retains the original guest capability for the claim and continues with the returned account board. + +## Connection and data + +The plugin connects directly to EasyGerber’s hosted MCP service at `https://www.easygerber.com/api/mcp`. It runs no local server, installer, hooks, or package downloads. Board layout, routing, and scoring run on EasyGerber’s servers. Droid can read relevant firmware locally to identify pin assignments; it sends only the board requirements, published component selections, schematic changes, board or organization identifiers, and feedback messages you approve for the requested work. It should not upload an entire repository or unrelated files. + +The remote service supplies catalog results, saved board data, previews, and private export links. Account access uses the service’s advertised OAuth flow and your consent. Do not paste credentials into chat or add tokens to plugin files. Organization permissions, plan limits, and normal request and compute protections apply. The service retains agent activity analytics for one year, including guest history after claim. Removing the plugin does not revoke account authorization or invalidate a private guest link; manage account connections in Droid or EasyGerber. + +To delete a specified account board, ask explicitly. The agent reads its current revision and uses `delete_board` only when the service advertises it. Deletion is permanent, has no restore operation, and cancels active jobs. It requires separate `boards:delete` consent through a client that supports requesting that scope, plus personal ownership or an organization owner/admin role; existing `boards:write` access is insufficient. A client registration that excludes this scope must be deliberately updated or replaced through the normal connection flow before consent; existing connections do not gain deletion access automatically. Guest deletion is unsupported, and a guest board must not be claimed merely to delete it. Signing in only to delete an account board does not authorize claiming a guest board. Only `{ boardId, deleted: true }` confirms deletion; `not_found` or a lost response does not. + +Creating or exporting a board does not purchase fabrication, make the design public, or delete the source board. A successful layout check is not a safety certification. The MIT license covers this integration package; the hosted service and private engines have separate terms. + +## Feedback and support + +Ask Droid to send EasyGerber a bug report, feature request, or general feedback. The `submit_feedback` tool sends only a message you ask or agree to share, from 10 to 2000 characters after trimming, to a private administrator inbox. It does not automatically attach transcripts, raw diagnostics, board exports, credentials, or private links. Anonymous feedback needs no account, guest session, or board. Existing valid account or guest access can attribute a report without additional board permissions; rejected credentials do not silently become anonymous. A guest board must never be claimed merely to submit feedback. + +The agent reuses the same request ID and identical report when retrying an uncertain submission. A receipt ID and timestamp confirm submission, without promising a response or roadmap commitment. If the connection or service is unavailable, use [GitHub Issues](https://github.com/EasyGerber/easygerber-agent-plugin/issues). Issues are public and require a GitHub account to post; remove credentials, private links, and confidential board data before publishing. + +See [documentation and support](https://easygerber.com/agents), [privacy policy](https://easygerber.com/privacy), and [terms](https://easygerber.com/terms). + +Submission and support contact: hello@easygerber.com. diff --git a/plugins/easygerber/assets/icon.svg b/plugins/easygerber/assets/icon.svg new file mode 100644 index 0000000..54e8565 --- /dev/null +++ b/plugins/easygerber/assets/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/plugins/easygerber/assets/logo.svg b/plugins/easygerber/assets/logo.svg new file mode 100644 index 0000000..afb8105 --- /dev/null +++ b/plugins/easygerber/assets/logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/plugins/easygerber/mcp.json b/plugins/easygerber/mcp.json new file mode 100644 index 0000000..c377ee3 --- /dev/null +++ b/plugins/easygerber/mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "easygerber": { + "type": "http", + "url": "https://www.easygerber.com/api/mcp" + } + } +} diff --git a/plugins/easygerber/skills/easygerber/SKILL.md b/plugins/easygerber/skills/easygerber/SKILL.md new file mode 100644 index 0000000..e6586d2 --- /dev/null +++ b/plugins/easygerber/skills/easygerber/SKILL.md @@ -0,0 +1,28 @@ +--- +name: easygerber +description: Create, inspect, revise, export, or explicitly delete EasyGerber circuit boards, or submit user-requested EasyGerber feedback, using its remote MCP tools. Use for EasyGerber board work, bug reports, and feature requests; ordinary firmware-only edits do not require this skill. +--- + +# EasyGerber board design + +Use the installed EasyGerber MCP tools for the requested board workflow. Hosts may prefix tool names differently; discover the tools available on the EasyGerber connection and follow their current schemas. If the connection is missing, direct the user to https://easygerber.com/agents. Never ask for tokens in chat or read credentials from project files. + +This skill expects `check_board_layout` for saved-layout blocker checks. If the connection does not advertise it, report that the service and integration versions do not match; do not substitute another tool or treat an unavailable check as a pass. + +EasyGerber's production service supports one guest board per session without an account. For a new board, finish any pending guest claim first, then reuse this task's guest session or already authorized account. If neither is established, call `start_guest_session` directly: success supplies the needed guest session; `account_connected` means no guest was created and you should use the connected account. Do not use `get_profile` or `list_organizations` to discover whether an account is connected, including parallel probes. Users do not need to choose an account mode or mention guests. One guest board supports previews and both manufacturing ZIP and `.egb` exports before signup, with no lifetime operation caps or automatic expiry when `expiresAt` is null; normal request-rate, complexity, and shared compute protections apply. Keep its capability token in tool arguments only, never in project files, logs, or ordinary messages; the private viewer link returned by the service is the only user-facing exception and is needed to return to the board. Read the guest section of [the workflow reference](references/workflow.md) before starting or claiming a guest board. Existing account boards and organization work require the host's sign-in flow; an expired account connection is not permission to recreate private work as a guest. + +When the user chooses sign-in or account board work with a guest board in this task, automatically save that board to their personal account. Signing in solely to delete an account board or submit feedback does not authorize claiming a guest board; never claim a guest board merely to delete it or send feedback. Use `claim_guest_board` with its original `guestToken` to initiate account authorization, then retry that same claim immediately when authentication resumes. Do not ask a separate “Keep board?” question or use `get_profile` as a substitute for the pending claim. Follow the workflow reference for busy retries and the returned account board ID. Generic native Settings **Authenticate** has no guest-board context; after that flow, the agent must resume the claim to complete the save. + +Read relevant firmware locally to extract pin assignments, signal names, power requirements, and connector needs. Send the minimum board requirements and schematic data needed for the request; do not upload the whole repository or unrelated files. Clarify electrical choices that cannot be inferred, such as an ambiguous power supply or conflicting pin assignments. + +For account board work, complete any pending guest claim first, then use `get_profile` to identify personal ownership and `list_organizations` when the user requests organization board work. New account boards belong to the personal account by default; pass `organizationId` only for the organization the user requested. Existing board operations use the board's saved ownership. Authorization remains limited by the user's permissions in that organization. + +Read [the workflow reference](references/workflow.md) for board creation, revision, generation, validation, and export. Search and inspect published catalog parts before connecting them. Preserve catalog IDs, pin identities, footprints, and available 3D models. Never invent component records or replace published footprints. Author the thin schematic and app-visible settings; the server hydrates catalog data and hidden routing/manufacturing constraints. + +Inspect an existing board before editing it. Apply only the requested changes and use the revision/concurrency fields required by the live tool schema. On a conflict, reload the board and reconcile the user's change; do not overwrite a newer revision blindly. Board generation is asynchronous: retain its returned generation ID, inspect its status, and report results or actionable failures. Reuse an existing returned operation when a request outcome is uncertain instead of starting duplicate work. + +Use `delete_board` only for an explicit user request to delete a specified account board, never for unsolicited cleanup. Deletion is permanent, has no restore operation, and cancels active jobs. It requires separately approved `boards:delete` access plus personal ownership or an organization owner/admin role; `boards:write` is insufficient. Read `get_board` first and pass its revision as `expectedRevision`. Guest boards cannot be deleted through this tool. Read the deletion section of the workflow reference before calling it. Report success only from `{ boardId, deleted: true }`; `not_found` can mean unavailable, insufficient ownership, or already absent and does not prove this request deleted the board. + +Use `submit_feedback` only when the user asks or agrees to send a bug report, feature request, or general feedback to EasyGerber. Read the feedback section of the workflow reference first. Send a concise approved message, never automatic transcripts, raw diagnostics, board exports, credentials, or private links. Feedback can be anonymous without signing in, starting a guest session, or creating a board; existing valid account or guest access can attribute it. Do not expand board permissions for feedback. Return the receipt without promising a response or roadmap commitment. If the connection or service is unavailable, offer [GitHub Issues](https://github.com/EasyGerber/easygerber-agent-plugin/issues) and explain that issues are public before any posting. + +Keep actions within the user's requested scope. Creating, revising, or exporting a board does not authorize deletion, public sharing, or purchasing fabrication. Explain returned electrical or manufacturing issues accurately; successful generation or no blocking issues is not a safety certification. Return the board link and requested artifacts, and distinguish saved, generated, exported, and explicitly confirmed deleted states. diff --git a/plugins/easygerber/skills/easygerber/references/workflow.md b/plugins/easygerber/skills/easygerber/references/workflow.md new file mode 100644 index 0000000..7cd37e7 --- /dev/null +++ b/plugins/easygerber/skills/easygerber/references/workflow.md @@ -0,0 +1,91 @@ +# Board workflow + +The server tool schema is authoritative for field names, allowed settings, required scopes, and result shapes. The integration exposes these capabilities: + +| Purpose | Tools | +| --- | --- | +| Guest board access and account claim | `start_guest_session`, `claim_guest_board` | +| Personal account and organizations | `get_profile`, `list_organizations` | +| Published component selection | `search_parts`, `get_part` | +| Saved boards and schematic revisions | `list_boards`, `get_board`, `create_board`, `update_board` | +| Explicitly requested account-board deletion | `delete_board` | +| Layout jobs | `generate_layout`, `get_generation`, `stop_generation` | +| Layout blocker checks and manufacturing artifacts | `check_board_layout`, `export_board` | +| User-approved bug reports, feature requests, and general feedback | `submit_feedback` | + +## Guest trial and account claim + +For a new board, finish any pending guest claim, then reuse the task's existing guest session or established account authorization. When neither is established, call `start_guest_session` using its current schema without first calling `get_profile` or `list_organizations`, including in parallel. Those account-only tools can prompt for sign-in before a guest can start. The ordinary tool error `account_connected` means an account is already authorized and no guest session was created; continue with that account, using `get_profile` only if needed for account work. A real OAuth or permission failure still requires the normal reconnect or permission flow; never remove credentials or downgrade to guest access. + +A successful `start_guest_session` returns `guestToken`, `expiresAt`, `limits`, and `viewerUrl`. Retain these for this task. `expiresAt: null` means no scheduled expiration, and `limits: { boards: 1 }` allows one guest board with no lifetime caps on edits, layouts, checks, previews, or exports. Starting a session is not an idempotent recovery operation: each successful call creates a new session and cannot recover a lost one. If its response is lost or ambiguous, stop and explain the uncertainty; do not repeat the start automatically. Reuse an existing session and board-operation request IDs after ambiguous board-operation failures; do not start another session to bypass the board limit, a denial, or service protections. The board limit is per session, not a promise of one verified trial per person. Guest support in a server schema does not prove support in every client. + +Pass `guestToken` in supported tool arguments. It authorizes this guest session's catalog access and board workflow, not private account boards or organizations. Do not send an organization ID for guest work. Guest mode supports saving one board, app-supported edits, layout, blocker checks, preview, and both manufacturing ZIP and EasyGerber exports before signup. The server's returned limits and nullable expiry are authoritative. Normal request-rate, complexity, and shared compute protections still apply; follow any retry guidance without changing identities or requiring signup to continue editing the same guest board. `guest_session_required` means a new trial can start if that matches the user's request. `guest_session_unavailable` can mean invalid, revoked, claimed, or an expired finite legacy session; it is not permission to replace the session automatically. Do not invent a deadline or renewal for a null expiry. + +Treat the guest token as a private capability. Do not print it, put it in a repository, add it to a commit, or record it in analytics or diagnostic logs. Keep it in the tool context, and give the user only the private viewer link returned by the service when they need to inspect or return to their board. Anyone with that link can access the guest board, and losing the capability/link prevents guest recovery. Do not shorten the link through an external service or make it public. Download links are private and expire separately after fifteen minutes; export objects become eligible for cleanup after twenty-four hours. Neither artifact timer expires the guest board. + +When the user chooses sign-in or account board work while this task has a guest board, save it to their personal account automatically as part of that transition. Signing in solely to delete an account board or submit feedback does not authorize claiming a guest board; never claim a guest board merely to delete it or send feedback. Call `claim_guest_board` with the original `guestToken` to initiate the client's normal OAuth flow, then retry the same claim immediately after authentication resumes with authorized `boards:write` access. Normal account consent is sufficient; do not ask a separate “Keep board?” question, wait for another save request, or call `get_profile` and leave the guest board unclaimed. If the user signs in through generic native Settings **Authenticate**, resume this pending claim when the agent continues: that callback has no guest-board context and cannot by itself guarantee an immediate save. Signing in from the private guest viewer saves the board through that viewer's account flow. Merely opening a guest preview in an already signed-in browser does not transfer it; do not treat that view as an account transition. + +Claiming copies the saved design into personal account ownership and returns a new board ID. Retain that ID, use the account board link, and call `get_board` without a guest token to read its current state and revision before any further writes. Successful claim revokes the old guest token and viewer session; do not use the guest ID as the account board ID. Retain the original token until the claim result is known. A failed or interrupted claim must preserve it for retry; repeating the same claim for the same account is safe even if the first response was lost. Never create a replacement guest session or board to recover a pending claim. If guest access is unavailable, explain the result without promising restoration; locally downloaded exports are separate files the user can keep. + +Finish polling an active guest layout before switching the MCP connection to OAuth. If a claim returns `guest_board_busy`, keep the original capability, wait for the existing job to finish, and automatically retry the same claim, following any retry guidance without rapid polling. Do not cancel the layout to complete the save, ask the user to retry manually, disconnect the account, or mix credentials to regain guest polling. The private viewer can refresh the saved board but does not report job progress. + +Other account tools may return `authentication_required`; use the client's normal OAuth flow for account work without an existing guest board. If an expired or invalid account credential is rejected, reconnect the account; never downgrade it to guest access. Once an account is authorized, only `claim_guest_board` receives the original guest token to transfer that board. Omit guest tokens from ordinary account calls; mixing credentials is rejected as `conflicting_credentials`. Account ownership provides account-based recovery and additional boards under normal plan limits; signup is not required merely to prevent a guest board from expiring. + +## Create from firmware or requirements + +1. Identify the board requirements and use the existing guest session or authorized account ownership. For account work, use an organization only when requested; otherwise use personal ownership. Read only relevant firmware files to map hardware pin names to signals. Distinguish firmware-defined choices from missing electrical requirements. +2. Search the published catalog and use `get_part` to confirm part identity, available pin data, electrical compatibility, essential supporting circuitry, and the requested connector form factor. Firmware pin labels describe signals; map them through real catalog pins. When no suitable published part exists, explain the missing capability and ask about an acceptable published alternative. +3. Submit the thin schematic using the live `create_board` schema: catalog part references, instance identities, connections, and visible settings. Include a fresh UUID `requestId` for the operation; retain it for any retry of the same unchanged request. The server resolves component geometry, models, and routing constraints. This also applies to test coupons. +4. Retain the saved board ID and revision. If layout generation is requested, call `generate_layout` and retain its job ID. Report a saved schematic separately from a completed layout. + +The compact intent format for `create_board` and `update_board` uses string arrays for parts: `[id, dbId, value]`, with an optional fourth `designator` when the printed label differs from `id`. `id` identifies the instance in this design; `dbId` is the published catalog ID returned by `get_part`; the required third item is the value/display label. Connections are objects with `net`, `class` (`power`, `signal`, or `ground`), and `pins`; each pin is exactly `[partId, padId]`, both strings. Use this format even if the host renders nested tool fields as `unknown`; the live schema remains authoritative. + +For example, this intent connects two verified connector pads. `inputConnector` and `outputConnector` are the `data` objects returned by `get_part`, and `inputPadId` and `outputPadId` are their verified string pad IDs: + +```js +const intent = { + parts: [ + ["J1", inputConnector.id, "Input"], + ["J2", outputConnector.id, "Output"], + ], + connections: [ + { net: "SIGNAL", class: "signal", pins: [["J1", inputPadId], ["J2", outputPadId]] }, + ], +}; +``` + +## Revise and generate + +Read `get_board` before `update_board`. Preserve component/catalog identities and fields outside the requested change. Pass the returned board revision as `expectedRevision` and a UUID `requestId` for a new update or generation operation. Reuse that request ID only when retrying the identical operation. If the tool rejects a revision, retrieve the current board and reconcile before submitting a new request. On validation errors, correct the reported input rather than weakening hidden constraints. + +After `generate_layout`, use `get_generation` with the returned ID and follow any suggested polling interval. Stop polling when completed, failed, or cancelled; do not loop rapidly. After completion, call `get_board` to read the saved revision and preview before checking or exporting. `stop_generation` is for a user-requested stop or an explicitly superseded job. A timeout does not establish failure: inspect the known job before resubmitting. + +## Check and export + +Use `check_board_layout` to check the saved layout. Its `validation` reports `hasBlockingIssues` and actionable `blockingIssues`; report those issues or say that no blocking issues were found. Numeric scores and deductions are not exposed. A null `validation` on a board read means it has no current assessment, not that it passed; generate a fresh layout if needed and run the check. Use `export_board` for the manufacturing files the user asks for. Link returned artifacts or download them to a user-requested local destination using the host's tools. Export links may expire; request a fresh export if needed. Do not infer that exporting orders a physical board. + +## Permission and limits + +Ordinary account workflows use `boards:read`, `boards:write`, `boards:generate`, and `boards:export`. The separate `boards:delete` scope permits deletion only after explicit consent; an existing write grant does not include it. The installer and default client configurations retain the ordinary scopes. Existing client registrations may also exclude `boards:delete`: the client must deliberately reconnect or re-register with that scope allowed and obtain fresh consent through normal OAuth. Neither existing registrations nor grants gain deletion access automatically. If the client cannot request and obtain additional deletion consent, explain that limitation without silently changing default scopes or claiming deletion occurred. Authorization does not bypass organization membership, the existing plan, quotas, or compute limits. Guest access permits one board with no lifetime operation caps; request-rate, complexity, and shared compute protections remain. If a tool returns an authorization, rate, admission, or unsupported-setting error, explain the concrete restriction and next step. Do not change ownership or credentials to work around it. Keep private board content, guest viewer links, and signed download URLs within the user's task. + +## Delete a specified account board + +Delete only a board the user explicitly asked to delete. Do not delete source boards after exporting, remove test boards as unsolicited cleanup, or infer deletion from a request to start over. If the target is unclear, identify the intended account board before proceeding. This action is permanent, has no restore operation, and cancels active jobs on that board; explain these effects when carrying out the request. + +Use `delete_board` only when the connected service advertises it. It requires the separate `boards:delete` OAuth scope, explicitly approved through the client's normal consent flow. `boards:write` does not authorize deletion. The account must own the personal board or hold an owner/admin role in its organization; other organization roles cannot delete it. OAuth consent alone does not authorize deleting any particular board. Guest deletion is unsupported, and claiming a guest board merely to delete it is not an alternative. + +For installer-managed Codex connections without a configured OAuth client ID, the [public integration README](https://github.com/EasyGerber/easygerber-agent-plugin#delete-an-account-board) provides verified opt-in registration commands. They require fresh consent and leave default scopes unchanged. Do not apply that registration-reset procedure to other clients or fixed-client-ID connections. + +Read the specified board with `get_board`, then call `delete_board` with that `boardId` and the current `expectedRevision`, without a guest token. If obtaining additional consent interrupts the task, read the board again before deleting it. A revision conflict requires another read and reconciliation with the user's request; do not blindly replace the revision or delete a different board. + +Only `{ boardId, deleted: true }` confirms successful deletion. Unavailable boards, insufficient ownership, and repeated requests for an already absent board return the same `not_found` result. Do not describe that result as successful deletion or infer whether an inaccessible board exists. If the deletion response is lost, report the outcome as uncertain; a later missing-board response does not prove that the original call succeeded. Do not create a replacement board or claim a guest board to resolve that uncertainty. + +## Send feedback with the user's agreement + +Use `submit_feedback` only when the user asks or agrees to send feedback to EasyGerber. Discussing a problem or asking for a fix does not by itself authorize a report. Choose `category` as `bug`, `feature_request`, or `general`, and send a concise `message` of 10–2000 characters after trimming, describing the issue or request the user agreed to share. Include only relevant, non-secret reproduction details. Never automatically attach or copy conversation transcripts, raw diagnostics, board exports, credentials, guest tokens, private viewer links, or signed downloads into the message. The tool accepts no attachments. + +Feedback needs no account, board, new guest session, or additional board scope. With valid connected OAuth, omit `guestToken` and let the service attribute the report to that account. Otherwise, an existing valid `guestToken` may attribute it to that session; omit it for anonymous feedback. Do not call `get_profile`, create or claim a board, start a guest session, or request broader permissions merely to send feedback. Rejected existing credentials remain denied: use the normal reconnect flow or offer the fallback below, without removing credentials or changing identities to bypass the denial. Signing in solely for feedback does not authorize a guest-board claim. + +Generate a UUID `requestId` for each new submission. If its response is lost, retry with the same request ID, category, message, and attribution; do not create a second report with a new ID. Follow returned rate-limit guidance without changing sessions or credentials. Success returns `{ id, createdAt, status: "submitted" }`, including on an identical retry. Return that receipt's ID and timestamp only after success. Receipt confirms storage in EasyGerber's private administrator inbox, not a reply, issue status, or roadmap commitment; there is no public feedback lookup or status tool. + +If `submit_feedback` is unavailable or the MCP connection or service cannot accept the report, offer [GitHub Issues](https://github.com/EasyGerber/easygerber-agent-plugin/issues). Explain that GitHub issues are public and require a GitHub account to post. Offer a redacted draft and obtain the user's agreement to public posting; approval to send private feedback does not authorize publishing it. Keep credentials, private links, board contents, and other confidential information out of public reports. diff --git a/skills/easygerber b/skills/easygerber new file mode 120000 index 0000000..03d543e --- /dev/null +++ b/skills/easygerber @@ -0,0 +1 @@ +../plugins/easygerber/skills/easygerber \ No newline at end of file