Privacy policy
PCBWay Studio MCP ("the service") is operated by Manuel Pérez
(@mperez90). This document explains what personal data the service
collects, how it is used, where it is stored, and how to exercise your
rights under the GDPR and similar regimes.
If you have any question about this policy, write to <[email protected]>.
_Last updated: 2026-04-10_
The service is a Model Context Protocol (MCP) server for AI-assisted PCB
design. It is invoked by an upstream LLM client (Claude, ChatGPT, an IDE
plugin, etc.) on behalf of an end user. We collect the minimum data
necessary to provide the requested functionality.
| Category | Examples | Why we receive it |
|---|---|---|
| Design files you upload | .kicad_sch, .kicad_pcb, .zip, BOM CSVs | Required to render previews, run validators, generate quotes, place orders. |
| Natural-language prompts | "Design a 5 V LED blinker with an STM32" | Forwarded to the upstream LLM client; the server only sees the parameters the client extracts. |
| API keys you supply | PCBWay, Mouser, DigiKey | Stored encrypted at rest in our database, never logged in plaintext. Used to make calls on your behalf. |
| Email address (optional) | If you sign up for order notifications | Sent only to Resend, our transactional email provider, when you ask for a notification. |
| Category | Retained | How |
|---|---|---|
| HTTP request metadata (path, method, status, latency) | 30 days | Local journald + offsite Hetzner Storage Box copy |
| MCP session record (session id, tool count, timestamps) | Indefinite (session) / 30 days (PII) | SQLite via better-sqlite3 |
Client name + version (clientInfo) | Indefinite | SQLite |
| User agent | 30 days | SQLite — older entries are pruned automatically |
| IP address | Hashed after 30 days (sha256, irreversible) | SQLite, see storage/access-log.ts |
| API key hash | Indefinite | sha256 fingerprint only — the raw key is never persisted in the access log |
We honor the DNT: 1 browser header and the x-mcp-dnt: 1 MCP header.
When DNT is set the IP address is hashed immediately instead of stored
raw, and the session is marked as do-not-track. Operators may also setMCP_DEFAULT_DNT=1 to make this the default for all sessions.
| Component | Provider | Region | Subprocessor data |
|---|---|---|---|
| Compute, database, file storage | Hetzner Cloud | Germany (Falkenstein / Nürnberg) | DPA |
| Reverse proxy / TLS | Self-hosted Caddy on the same Hetzner box | Germany | n/a |
| DNS / DDoS edge (optional) | Cloudflare | Global anycast | DPA |
| Transactional email (only when you opt in) | Resend | US (with EU option) | DPA |
| Component data lookups | Mouser API, DigiKey API, JLCPCB search | US / global | Only the part numbers you query |
| Quote and order forwarding | PCBWay API | China | The design files and BOM you submit for the quote |
| Optional GitHub App reviews | GitHub | US | Repository metadata, commit SHA, file diff |
| Optional crash tracking | Sentry (free tier) | EU | Stack traces, error types — no PII |
When you call place_order, get_quote, or any other tool that contacts
a third party, the relevant payload (your design files, BOM, contact
details) is transmitted to that third party. Their privacy policies
govern what they do with it.
| Activity | Legal basis |
|---|---|
| Running the design tools you invoke | Art. 6(1)(b) — performance of the contract you initiated |
| Storing your account and PCBWay key | Art. 6(1)(b) — performance of the contract |
| Access logging for security and abuse prevention | Art. 6(1)(f) — legitimate interest in maintaining the service |
| Transactional email (opt-in only) | Art. 6(1)(a) — your consent |
| Sending commission attribution to PCBWay (operator-side) | Art. 6(1)(f) — legitimate interest, no personal data shared |
/renders/<id>/...): 7 days, then automaticallycleanup_old_renders.
/reports/<id>.pdf): 30 days.You can shorten any of these by self-hosting and adjusting the relevant
environment variables. Operators self-hosting the code can tune retention
via the env vars described in the repository README.
The full security posture is documented in the v0.17.1 CHANGELOG.md
and summarized below:
127.0.0.1 and is not
reachable from the internet directly.
MCP_ADMIN_KEY), with non-admin callers receiving a generic
"tool not found" response so the existence of admin endpoints is not
leaked.
ssrfGuard(), which DNS-resolves the host and refuses
any IP in private, link-local, or loopback ranges.
pcbmcpMCP_DATA_ENCRYPTION_KEY (32-byte random).
systemd-run --scopeMemoryMax, CPUQuota, PrivateNetwork=yes, and
NoNewPrivileges=yes.
redactSecrets() to stripre_, GitHub PAT ghp_, OpenAI sk-,
AWS AKIA, Slack xox*, BEGIN PRIVATE KEY blocks).
We follow the principle of least privilege and patch dependencies on a
weekly Dependabot schedule.
Under the GDPR you have the right to:
forget_order and
forget_observed_components for self-service deletion of those
specific stores. For full account deletion, use the Delete account
button on the /account page or email the support address.
list_my_orders and list_observed_components which
return JSON dumps you can copy.
unsubscribe or the unsubscribe link in any email.
To exercise any of these rights, email <[email protected]> with
a brief description and the email or hashed identifier you used. We
respond within 30 days.
The service is not directed at children under 16 and we do not knowingly
collect data from them. If you believe we have collected data from a
child, please contact us so we can delete it.
When we update this policy we bump the date at the top and record the
change in CHANGELOG.md. Material changes (new subprocessors, new data
categories, expanded retention) are announced via the release notes for
the version that introduces them.
@mperez90)