Rewrite README with real-world example and project structure
This commit is contained in:
parent
9c47a49ec0
commit
a28eed3849
92
README.md
92
README.md
@ -1,21 +1,37 @@
|
|||||||
# mcp210x
|
# mcp210x
|
||||||
|
|
||||||
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.
|
It's MCP. It's CP210x. It was right there the whole time.
|
||||||
|
|
||||||
Built on [FastMCP](https://gofastmcp.com/) and Silicon Labs' `libcp210xmanufacturing` native library via Python ctypes.
|
An MCP server for customizing Silicon Labs CP210x USB-UART bridge devices — product strings, serial numbers, power config, udev rules, and device locking — through natural language in Claude Code.
|
||||||
|
|
||||||
## Why
|
Built on [FastMCP](https://gofastmcp.com/) with Python ctypes bindings to Silicon Labs' native `libcp210xmanufacturing` library.
|
||||||
|
|
||||||
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.
|
## The problem
|
||||||
|
|
||||||
This MCP server lets you customize devices conversationally:
|
You plug in three CP2102 boards. They all enumerate as:
|
||||||
|
|
||||||
|
```
|
||||||
|
Bus 001 Device 004: ID 10c4:ea60 Silicon Labs CP2102 USB to UART Bridge Controller
|
||||||
|
Bus 001 Device 005: ID 10c4:ea60 Silicon Labs CP2102 USB to UART Bridge Controller
|
||||||
|
Bus 001 Device 006: ID 10c4:ea60 Silicon Labs CP2102 USB to UART Bridge Controller
|
||||||
|
```
|
||||||
|
|
||||||
|
Which one is which? Unplug, replug, guess. `/dev/ttyUSB0` becomes `/dev/ttyUSB2` after a reboot. You write udev rules that match on nothing unique. The Silicon Labs GUI customization tool is 32-bit only and hasn't been updated since 2015.
|
||||||
|
|
||||||
|
## The fix
|
||||||
|
|
||||||
```
|
```
|
||||||
> What CP210x devices are connected?
|
> 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
|
Two devices found:
|
||||||
|
[0] RYLR998 0033001104645C0B00001130 (serial: 0001)
|
||||||
|
[1] RYLR998 0033001104645C0B00000D27 (serial: 0001)
|
||||||
|
|
||||||
|
> Set up a udev rule for device 0 so it always appears at /dev/rylr998-1130
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Each device gets a unique product string baked into its USB descriptor EPROM. Udev rules match on that string to create stable symlinks. Devices survive reboots, port reordering, and hub changes.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **List and inspect** connected CP210x devices (part number, VID/PID, strings, power, lock state)
|
- **List and inspect** connected CP210x devices (part number, VID/PID, strings, power, lock state)
|
||||||
@ -23,55 +39,67 @@ This MCP server lets you customize devices conversationally:
|
|||||||
- **Configure power** — max current draw, self-powered vs bus-powered
|
- **Configure power** — max current draw, self-powered vs bus-powered
|
||||||
- **Generate udev rules** — stable `/dev/` symlinks based on product string
|
- **Generate udev rules** — stable `/dev/` symlinks based on product string
|
||||||
- **Reset device** — trigger USB re-enumeration after changes
|
- **Reset device** — trigger USB re-enumeration after changes
|
||||||
- **Lock device** — permanently freeze configuration (with strict confirmation)
|
- **Lock device** — permanently freeze configuration (with strict confirmation gate)
|
||||||
- **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.
|
|
||||||
|
## Safety model
|
||||||
|
|
||||||
|
CP210x descriptor EPROM is one-time-programmable with limited write cycles. Writes can't be undone. Locks are permanent. The server enforces a tiered confirmation model:
|
||||||
|
|
||||||
|
| Operation | Confirmation |
|
||||||
|
|-----------|-------------|
|
||||||
|
| Reads | None |
|
||||||
|
| Writes (strings, power) | MCP elicitation if client supports it; proceeds otherwise |
|
||||||
|
| Lock | Elicitation **required**; hard-refuses without it |
|
||||||
|
|
||||||
|
The lock gate isn't just a warning — it returns an error and does not proceed if the MCP client can't present a confirmation dialog.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Linux x86_64
|
- Linux x86_64
|
||||||
- `libcp210xmanufacturing.so` — Silicon Labs CP210x manufacturing library
|
- `libcp210xmanufacturing.so` — Silicon Labs CP210x manufacturing library
|
||||||
- Python 3.10+
|
- Python 3.10+
|
||||||
- [uv](https://docs.astral.sh/uv/) (recommended)
|
- [uv](https://docs.astral.sh/uv/)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### 1. Install the native library
|
### 1. Native library
|
||||||
|
|
||||||
**Arch Linux (AUR package included):**
|
**Arch Linux** (AUR package included):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd aur/cp210xmanufacturing
|
cd aur/cp210xmanufacturing
|
||||||
makepkg -si
|
makepkg -si
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This installs the shared library, headers, and udev rules for non-root USB access.
|
||||||
|
|
||||||
**From source:**
|
**From source:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Extract AN721SW toolkit (included in docs/)
|
|
||||||
cd AN721SW/Linux/LibrarySourcePackages/cp210xmanufacturing
|
cd AN721SW/Linux/LibrarySourcePackages/cp210xmanufacturing
|
||||||
make LIB_ARCH=64
|
make LIB_ARCH=64
|
||||||
sudo make install
|
sudo make install
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
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/`.
|
You'll also need udev rules for non-root device access — copy `aur/cp210xmanufacturing/SiliconLabs.rules` to `/usr/lib/udev/rules.d/` and reload.
|
||||||
|
|
||||||
### 2. Install the MCP server
|
### 2. MCP server
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv tool install .
|
uv tool install .
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Add to Claude Code
|
### 3. Claude Code
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude mcp add cp210x -- uvx mcp210x
|
claude mcp add cp210x -- uvx mcp210x
|
||||||
```
|
```
|
||||||
|
|
||||||
Or for development (runs from source):
|
For development (runs from source):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude mcp add cp210x-local -- uv run --directory /path/to/cp2102-uart mcp210x
|
claude mcp add cp210x-local -- uv run --directory /path/to/this-repo mcp210x
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
@ -83,10 +111,10 @@ claude mcp add cp210x-local -- uv run --directory /path/to/cp2102-uart mcp210x
|
|||||||
| `set_product_string` | Write USB product string (max 126 chars) |
|
| `set_product_string` | Write USB product string (max 126 chars) |
|
||||||
| `set_manufacturer_string` | Write USB manufacturer string (max 45 chars) |
|
| `set_manufacturer_string` | Write USB manufacturer string (max 45 chars) |
|
||||||
| `set_serial_number` | Write USB serial number (max 63 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_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 |
|
| `set_self_powered` | Toggle self-powered vs bus-powered reporting |
|
||||||
| `reset_device` | USB disconnect/reconnect to apply changes |
|
| `reset_device` | USB disconnect/reconnect to apply changes |
|
||||||
| `lock_device` | **Permanently** freeze device configuration |
|
| `lock_device` | Permanently freeze device configuration |
|
||||||
| `setup_udev_rule` | Generate and install a udev rule for a stable `/dev/` symlink |
|
| `setup_udev_rule` | Generate and install a udev rule for a stable `/dev/` symlink |
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@ -104,19 +132,27 @@ Claude Code ──stdio──▶ FastMCP server (server.py)
|
|||||||
libusb ──▶ CP210x device
|
libusb ──▶ CP210x device
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
The native library uses **libusb** for device access, separate from the kernel's `cp210x` serial driver. Both coexist — you can read/write UART data over `/dev/ttyUSB0` while customizing USB descriptors through this server.
|
||||||
|
|
||||||
### Safety model
|
## Project structure
|
||||||
|
|
||||||
CP210x EPROM writes are one-time-programmable with limited write cycles. The server uses a tiered confirmation model:
|
```
|
||||||
|
mcp210x/
|
||||||
- **Reads** — no confirmation needed
|
├── src/mcp210x/
|
||||||
- **Writes** (strings, power) — requests confirmation via MCP elicitation; falls back to proceeding if the client doesn't support it
|
│ ├── server.py # FastMCP tool definitions and elicitation logic
|
||||||
- **Lock** — *always* requires elicitation; hard-refuses without it
|
│ ├── bindings.py # ctypes wrapper for libcp210xmanufacturing.so
|
||||||
|
│ └── __init__.py
|
||||||
|
├── aur/cp210xmanufacturing/
|
||||||
|
│ ├── PKGBUILD # Arch Linux package for the native library
|
||||||
|
│ └── SiliconLabs.rules # udev rules for non-root USB access
|
||||||
|
├── AN721SW/ # Silicon Labs toolkit (library source)
|
||||||
|
├── docs/ # Datasheets and application notes
|
||||||
|
└── pyproject.toml
|
||||||
|
```
|
||||||
|
|
||||||
## Complementary tools
|
## 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).
|
This server handles **device customization** (USB descriptors, power config). For **serial communication** (sending/receiving data over UART), use [mcserial](https://git.supported.systems/MCP/mcserial).
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user