From 3787f4e8a314780888b3838cb7bf1804a3cf065b Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Fri, 30 Jan 2026 12:19:38 -0700 Subject: [PATCH] Rewrite README with architecture, safety model, and setup guide --- README.md | 120 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 67f0f7d..10bb436 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,128 @@ -# CP210x MCP Server +# cp210x-mcp -MCP server for customizing Silicon Labs CP210x USB-UART bridge devices. Allows reading and writing USB descriptor strings, power configuration, and more. +MCP server for customizing Silicon Labs CP210x USB-UART bridge devices. Read and write USB descriptor strings, power configuration, and device lock state — all through natural language in Claude Code. + +Built on [FastMCP](https://gofastmcp.com/) and Silicon Labs' `libcp210xmanufacturing` native library via Python ctypes. + +## Why + +CP210x chips (CP2102, CP2102N, CP2104, etc.) store USB descriptor strings in one-time-programmable EPROM. Silicon Labs provides a GUI tool and a C library for customization, but both are clunky to use — especially when managing multiple identical devices that need unique identifiers. + +This MCP server lets you customize devices conversationally: + +``` +> What CP210x devices are connected? +> Change the product string of device 0 to "RYLR998 0033001104645C0B00001130" +> Set up a udev rule so it always appears at /dev/rylr998-1130 +``` ## Features -- List connected CP210x devices -- Read/write USB product string (device name) -- Read/write manufacturer string -- Read/write serial number -- Configure max power draw -- Set self-powered/bus-powered mode -- Reset device (USB re-enumeration) -- Lock device (permanent - prevents further changes) +- **List and inspect** connected CP210x devices (part number, VID/PID, strings, power, lock state) +- **Write USB descriptors** — product string, manufacturer, serial number +- **Configure power** — max current draw, self-powered vs bus-powered +- **Generate udev rules** — stable `/dev/` symlinks based on product string +- **Reset device** — trigger USB re-enumeration after changes +- **Lock device** — permanently freeze configuration (with strict confirmation) +- **Elicitation support** — write operations request confirmation when the MCP client supports it; graceful fallback otherwise. Lock is the exception: it *requires* explicit confirmation and will refuse if elicitation is unavailable. ## Requirements - Linux x86_64 -- `libcp210xmanufacturing.so` - Install via AUR package or build from source +- `libcp210xmanufacturing.so` — Silicon Labs CP210x manufacturing library +- Python 3.10+ +- [uv](https://docs.astral.sh/uv/) (recommended) ## Installation -### Install the library (Arch Linux) +### 1. Install the native library + +**Arch Linux (AUR package included):** ```bash cd aur/cp210xmanufacturing makepkg -si ``` -Or build from source: +**From source:** ```bash +# Extract AN721SW toolkit (included in docs/) cd AN721SW/Linux/LibrarySourcePackages/cp210xmanufacturing make LIB_ARCH=64 sudo make install sudo ldconfig ``` -### Install the MCP server +The library installs to `/usr/lib/libcp210xmanufacturing.so` and uses libusb to communicate with devices. You'll need udev rules for non-root access — the AUR package installs these automatically, or copy `aur/cp210xmanufacturing/SiliconLabs.rules` to `/usr/lib/udev/rules.d/`. + +### 2. Install the MCP server ```bash -# With uv (recommended) uv tool install . - -# Or with pip -pip install . ``` -## Usage - -### Add to Claude Code +### 3. Add to Claude Code ```bash claude mcp add cp210x -- uvx cp210x-mcp ``` -### Available Tools +Or for development (runs from source): + +```bash +claude mcp add cp210x-local -- uv run --directory /path/to/cp2102-uart cp210x-mcp +``` + +## Tools | Tool | Description | |------|-------------| -| `list_devices` | List connected CP210x devices | -| `get_device_info` | Get detailed device information | -| `set_product_string` | Set USB product string (device name) | -| `set_manufacturer_string` | Set USB manufacturer string | -| `set_serial_number` | Set USB serial number | -| `set_max_power` | Set max USB power draw (mA) | -| `set_self_powered` | Set self-powered vs bus-powered | -| `reset_device` | Reset device (USB re-enumeration) | -| `lock_device` | PERMANENTLY lock device config | +| `list_devices` | List connected CP210x devices with description and serial | +| `get_device_info` | Full device details — part number, VID/PID, strings, power, lock state | +| `set_product_string` | Write USB product string (max 126 chars) | +| `set_manufacturer_string` | Write USB manufacturer string (max 45 chars) | +| `set_serial_number` | Write USB serial number (max 63 chars) | +| `set_max_power` | Set max USB power draw in mA (0–500, rounded to nearest 2) | +| `set_self_powered` | Toggle self-powered vs bus-powered reporting | +| `reset_device` | USB disconnect/reconnect to apply changes | +| `lock_device` | **Permanently** freeze device configuration | +| `setup_udev_rule` | Generate and install a udev rule for a stable `/dev/` symlink | -### Example +## Architecture -```bash -# In Claude Code conversation: -> What CP210x devices are connected? -> Change the product name of device 0 to "My Custom Device" +``` +Claude Code ──stdio──▶ FastMCP server (server.py) + │ + ▼ + Python ctypes (bindings.py) + │ + ▼ + libcp210xmanufacturing.so + │ + ▼ + libusb ──▶ CP210x device ``` -## Relationship to mcserial +The native library uses **libusb** for device access, which is separate from the kernel's `cp210x` serial driver. Both can coexist — you can read/write UART data over `/dev/ttyUSB0` while simultaneously customizing USB descriptors through this server. -This MCP server complements [mcserial](https://github.com/ryanmalloy/mcserial) which handles serial port communication. Use this server for **device customization** (changing USB descriptors) and mcserial for **serial communication** (sending/receiving data over UART). +### Safety model + +CP210x EPROM writes are one-time-programmable with limited write cycles. The server uses a tiered confirmation model: + +- **Reads** — no confirmation needed +- **Writes** (strings, power) — requests confirmation via MCP elicitation; falls back to proceeding if the client doesn't support it +- **Lock** — *always* requires elicitation; hard-refuses without it + +## Complementary tools + +This server handles **device customization** (USB descriptors, power config). For **serial communication** (sending/receiving data over UART), use [mcserial](https://github.com/ryanmalloy/mcserial). + +## Reference + +- [CP2102 Datasheet](https://www.silabs.com/documents/public/data-sheets/CP2102-9.pdf) +- [AN721: Device Customization Guide](https://www.silabs.com/documents/public/example-code/AN721SW.zip) — source for `libcp210xmanufacturing` +- [AN197: Serial Communication Guide](https://www.silabs.com/documents/public/application-notes/an197-serial-communications-guide-cp210x.pdf) ## License