283 lines
8.6 KiB
Markdown
283 lines
8.6 KiB
Markdown
# Camera TRNG API Skill Documentation
|
||
|
||
This document describes how to use the Camera TRNG (True Random Number Generator) API as an MCP-compatible service.
|
||
|
||
## Overview
|
||
|
||
The Camera TRNG server provides quantum-based random number generation using thermal noise from a covered camera sensor. The API is accessible via HTTP and self-documents its capabilities through the `.well-known/mcp.json` endpoint.
|
||
|
||
## Discovery
|
||
|
||
The API can be discovered by fetching the MCP endpoint:
|
||
|
||
```bash
|
||
curl http://localhost:8787/.well-known/mcp.json
|
||
```
|
||
|
||
The response includes self-referencing URLs that use the request's hostname (from SNI/HTTP Host header), making it work correctly whether accessed via `localhost`, a domain name, or behind a reverse proxy.
|
||
|
||
## API Endpoints
|
||
|
||
### 1. Get Random Bytes (`/random`)
|
||
|
||
Generate cryptographically secure random bytes from camera sensor entropy.
|
||
|
||
**Parameters:**
|
||
- `bytes` (integer, default: 32, max: 1048576): Number of random bytes to generate
|
||
- `hex` (boolean, default: false): Return bytes as hexadecimal string instead of binary
|
||
|
||
**Examples:**
|
||
```bash
|
||
# Get 32 bytes as hex string
|
||
curl -s "http://localhost:8787/random?bytes=32&hex=true"
|
||
|
||
# Get 64 raw bytes saved to a file
|
||
curl -s "http://localhost:8787/random?bytes=64" -o random.bin
|
||
|
||
# Get 1 KB and pipe to xxd for hex viewing
|
||
curl -s "http://localhost:8787/random?bytes=1024" | xxd
|
||
|
||
# Get 1 MB of random data
|
||
curl -s "http://localhost:8787/random?bytes=1048576" -o random-1mb.bin
|
||
```
|
||
|
||
### 2. Stream Random Bytes (`/stream`)
|
||
|
||
Stream continuous random bytes. Useful for high-throughput applications or feeding entropy to other processes.
|
||
|
||
**Parameters:**
|
||
- `bytes` (integer, optional): Total bytes to stream (omit for unlimited)
|
||
- `hex` (boolean, default: false): Stream as hexadecimal strings instead of binary
|
||
|
||
**Examples:**
|
||
```bash
|
||
# Stream unlimited random bytes (binary, Ctrl-C to stop)
|
||
curl -N "http://localhost:8787/stream"
|
||
|
||
# Stream exactly 1 MB as hex
|
||
curl -N "http://localhost:8787/stream?bytes=1048576&hex=true"
|
||
|
||
# Stream hex to a file
|
||
curl -N "http://localhost:8787/stream?hex=true" > entropy.hex
|
||
|
||
# Pipe stream to another process
|
||
curl -N "http://localhost:8787/stream?bytes=4096" | openssl enc -aes-256-cbc -pass pass:test -in /dev/stdin
|
||
|
||
# Stream 10 KB of binary entropy, view as hex dump
|
||
curl -sN "http://localhost:8787/stream?bytes=10240" | xxd | head -40
|
||
```
|
||
|
||
### 3. List Cameras (`/cameras`)
|
||
|
||
List available camera devices on the system.
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -s "http://localhost:8787/cameras" | jq
|
||
```
|
||
|
||
**Response:**
|
||
```json
|
||
{
|
||
"cameras": [
|
||
{
|
||
"index": 0,
|
||
"human_name": "FaceTime HD Camera",
|
||
"description": "Built-in camera",
|
||
"misc": ""
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 4. Health Check (`/health`)
|
||
|
||
Check server status, pool level, and harvester state.
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -s "http://localhost:8787/health" | jq
|
||
```
|
||
|
||
**Response:**
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"pool_bytes_available": 262144,
|
||
"total_camera_bytes_harvested": 1048576,
|
||
"csprng_seeded_from_camera": true
|
||
}
|
||
```
|
||
|
||
### 5. Quantum Dice (`/dice`)
|
||
|
||
Roll quantum-random dice.
|
||
|
||
**Parameters:**
|
||
- `d` (integer, default: 6, range: 2–256): Number of sides
|
||
- `count` (integer, default: 1, max: 100): Number of dice to roll
|
||
|
||
**Examples:**
|
||
```bash
|
||
# Roll one d6
|
||
curl -s "http://localhost:8787/dice" | jq
|
||
|
||
# Roll 5d20
|
||
curl -s "http://localhost:8787/dice?d=20&count=5" | jq
|
||
```
|
||
|
||
### 6. Quantum Password Generator (`/password`)
|
||
|
||
Generate a cryptographically random password.
|
||
|
||
**Parameters:**
|
||
- `length` (integer, default: 20, max: 128): Password length
|
||
- `charset` (string, default: "alphanumeric"): One of `alphanumeric`, `full`, `hex`, or flag combos (`l`ower, `u`pper, `d`igit, `s`ymbol)
|
||
- `exclude_ambiguous` (boolean, default: false): Remove `0 O o I l 1 |`
|
||
|
||
**Examples:**
|
||
```bash
|
||
# Default 20-char alphanumeric password
|
||
curl -s "http://localhost:8787/password" | jq -r .password
|
||
|
||
# 32-char with full charset, no ambiguous chars
|
||
curl -s "http://localhost:8787/password?length=32&charset=full&exclude_ambiguous=true" | jq -r .password
|
||
|
||
# Hex-only 64-char token
|
||
curl -s "http://localhost:8787/password?length=64&charset=hex" | jq -r .password
|
||
```
|
||
|
||
### 7. Quantum Coin Flip (`/coin`)
|
||
|
||
Flip a quantum coin.
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -s "http://localhost:8787/coin" | jq -r .result
|
||
```
|
||
|
||
### 8. Quantum 8 Ball (`/8ball`)
|
||
|
||
Get a quantum-random Magic 8 Ball answer.
|
||
|
||
**Parameters:**
|
||
- `question` (string, optional): The question to ask
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -s "http://localhost:8787/8ball?question=Will+it+work" | jq
|
||
```
|
||
|
||
## MCP Integration
|
||
|
||
The API implements the Model Context Protocol (MCP) specification, allowing AI assistants and other MCP clients to discover and use the TRNG service automatically.
|
||
|
||
### MCP Tools
|
||
|
||
The following tools are exposed via MCP:
|
||
|
||
1. **get-random**: Generate random bytes (cryptographically secure)
|
||
2. **get-stream**: Stream random bytes continuously
|
||
3. **list-cameras**: Discover available cameras
|
||
4. **health-check**: Verify server status
|
||
|
||
### Self-Referencing URLs
|
||
|
||
The MCP endpoint (`/.well-known/mcp.json`) automatically detects the request's hostname from:
|
||
- HTTP `Host` header
|
||
- `X-Forwarded-Proto` header (for reverse proxy scenarios)
|
||
|
||
This ensures URLs in the MCP response always reference the correct origin, whether accessed via:
|
||
- `localhost:8787`
|
||
- `trng.example.com`
|
||
- Behind a reverse proxy with forwarded headers
|
||
|
||
## Usage Examples
|
||
|
||
### Python
|
||
```python
|
||
import requests
|
||
|
||
# Get 32 random bytes
|
||
resp = requests.get("http://localhost:8787/random?bytes=32")
|
||
random_bytes = resp.content
|
||
print(random_bytes.hex())
|
||
|
||
# Stream random data
|
||
with requests.get("http://localhost:8787/stream?hex=true", stream=True) as r:
|
||
for chunk in r.iter_content(chunk_size=64):
|
||
print(chunk.decode(), end="")
|
||
|
||
# Tools
|
||
print(requests.get("http://localhost:8787/dice?d=20&count=3").json())
|
||
print(requests.get("http://localhost:8787/password?length=24&charset=full").json()["password"])
|
||
print(requests.get("http://localhost:8787/coin").json()["result"])
|
||
print(requests.get("http://localhost:8787/8ball").json()["answer"])
|
||
```
|
||
|
||
### JavaScript/Node.js
|
||
```javascript
|
||
// Get random bytes
|
||
const resp = await fetch("http://localhost:8787/random?bytes=32");
|
||
const buffer = await resp.arrayBuffer();
|
||
const bytes = new Uint8Array(buffer);
|
||
|
||
// Stream random data
|
||
const stream = await fetch("http://localhost:8787/stream?hex=true");
|
||
const reader = stream.body.getReader();
|
||
const decoder = new TextDecoder();
|
||
while (true) {
|
||
const { done, value } = await reader.read();
|
||
if (done) break;
|
||
process.stdout.write(decoder.decode(value));
|
||
}
|
||
|
||
// Tools
|
||
const dice = await (await fetch("http://localhost:8787/dice?d=6&count=5")).json();
|
||
const pw = await (await fetch("http://localhost:8787/password?length=20")).json();
|
||
const coin = await (await fetch("http://localhost:8787/coin")).json();
|
||
const ball = await (await fetch("http://localhost:8787/8ball")).json();
|
||
```
|
||
|
||
### curl (comprehensive)
|
||
```bash
|
||
# ── Random ────────────────────────────────────────────
|
||
curl -s "http://localhost:8787/random?bytes=32&hex=true"
|
||
curl -s "http://localhost:8787/random?bytes=1024" -o random.bin
|
||
curl -s "http://localhost:8787/random?bytes=256" | xxd
|
||
|
||
# ── Stream ────────────────────────────────────────────
|
||
curl -N "http://localhost:8787/stream"
|
||
curl -N "http://localhost:8787/stream?bytes=1024&hex=true"
|
||
curl -N "http://localhost:8787/stream?hex=true" > entropy.hex
|
||
|
||
# ── Tools ─────────────────────────────────────────────
|
||
curl -s "http://localhost:8787/dice?d=20&count=3" | jq
|
||
curl -s "http://localhost:8787/password?length=24" | jq -r .password
|
||
curl -s "http://localhost:8787/coin" | jq -r .result
|
||
curl -s "http://localhost:8787/8ball?question=Ship+it" | jq
|
||
|
||
# ── Health & Discovery ────────────────────────────────
|
||
curl -s "http://localhost:8787/health" | jq
|
||
curl -s "http://localhost:8787/cameras" | jq
|
||
curl -s "http://localhost:8787/.well-known/mcp.json" | jq
|
||
```
|
||
|
||
## Limitations
|
||
|
||
- Maximum 1 MB per request (`/random`)
|
||
- Maximum 4 concurrent requests
|
||
- Requires a camera device with covered lens
|
||
- Performance depends on camera frame rate
|
||
|
||
## Security Notes
|
||
|
||
- No authentication required (intended for local/trusted networks)
|
||
- Random data is only from camera input; otherwise requests fail
|
||
- Consider rate limiting in production deployments
|
||
|
||
## See Also
|
||
|
||
- `TECHNICAL.md` - Technical implementation details
|
||
- `README.md` - Project overview and setup instructions
|