Add comprehensive curl/stream examples to all code tabs and skill.md
- Expand index.html code examples (curl, Python, JS, Rust, Go) to include /stream, /dice, /password, /coin, /8ball, and /health endpoints alongside /random — stream examples were previously missing - Fix skill.md: remove duplicated stream code block, add dedicated sections for dice, password, coin, and 8ball endpoints with full curl examples and parameter docs - Add comprehensive "curl (comprehensive)" cheat-sheet section to skill.md covering every endpoint in one block Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
5b49685ae9
commit
1ce1c833b6
191
skill.md
191
skill.md
|
|
@ -28,19 +28,22 @@ Generate cryptographically secure random bytes from camera sensor entropy.
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
```bash
|
```bash
|
||||||
# Get 32 bytes as binary
|
# Get 32 bytes as hex string
|
||||||
curl "http://localhost:8787/random?bytes=32" -o random.bin
|
curl -s "http://localhost:8787/random?bytes=32&hex=true"
|
||||||
|
|
||||||
# Get 64 bytes as hex string
|
# Get 64 raw bytes saved to a file
|
||||||
curl "http://localhost:8787/random?bytes=64&hex=true"
|
curl -s "http://localhost:8787/random?bytes=64" -o random.bin
|
||||||
|
|
||||||
# Get 1KB of random data
|
# Get 1 KB and pipe to xxd for hex viewing
|
||||||
curl "http://localhost:8787/random?bytes=1024" -o random.bin
|
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`)
|
### 2. Stream Random Bytes (`/stream`)
|
||||||
|
|
||||||
Stream continuous random bytes using Server-Sent Events (SSE) format. Useful for high-throughput applications.
|
Stream continuous random bytes. Useful for high-throughput applications or feeding entropy to other processes.
|
||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
- `bytes` (integer, optional): Total bytes to stream (omit for unlimited)
|
- `bytes` (integer, optional): Total bytes to stream (omit for unlimited)
|
||||||
|
|
@ -48,26 +51,20 @@ Stream continuous random bytes using Server-Sent Events (SSE) format. Useful for
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
```bash
|
```bash
|
||||||
# Stream unlimited random bytes (binary)
|
# Stream unlimited random bytes (binary, Ctrl-C to stop)
|
||||||
curl -N "http://localhost:8787/stream"
|
curl -N "http://localhost:8787/stream"
|
||||||
|
|
||||||
# Stream exactly 1MB
|
# Stream exactly 1 MB as hex
|
||||||
curl -N "http://localhost:8787/stream?bytes=1048576"
|
curl -N "http://localhost:8787/stream?bytes=1048576&hex=true"
|
||||||
|
|
||||||
# Stream as hexadecimal strings
|
# Stream hex to a file
|
||||||
curl -N "http://localhost:8787/stream?hex=true"
|
curl -N "http://localhost:8787/stream?hex=true" > entropy.hex
|
||||||
|
|
||||||
# Stream limited bytes as hex
|
# Pipe stream to another process
|
||||||
curl -N "http://localhost:8787/stream?bytes=1024&hex=true"
|
curl -N "http://localhost:8787/stream?bytes=4096" | openssl enc -aes-256-cbc -pass pass:test -in /dev/stdin
|
||||||
```bash
|
|
||||||
# Stream unlimited random bytes
|
|
||||||
curl -N "http://localhost:8787/stream"
|
|
||||||
|
|
||||||
# Stream exactly 1MB
|
# Stream 10 KB of binary entropy, view as hex dump
|
||||||
curl -N "http://localhost:8787/stream?bytes=1048576"
|
curl -sN "http://localhost:8787/stream?bytes=10240" | xxd | head -40
|
||||||
|
|
||||||
# Stream as hex
|
|
||||||
curl -N "http://localhost:8787/stream?hex=true"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. List Cameras (`/cameras`)
|
### 3. List Cameras (`/cameras`)
|
||||||
|
|
@ -76,7 +73,7 @@ List available camera devices on the system.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8787/cameras"
|
curl -s "http://localhost:8787/cameras" | jq
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response:**
|
**Response:**
|
||||||
|
|
@ -95,14 +92,81 @@ curl "http://localhost:8787/cameras"
|
||||||
|
|
||||||
### 4. Health Check (`/health`)
|
### 4. Health Check (`/health`)
|
||||||
|
|
||||||
Check if the TRNG server is running.
|
Check server status, pool level, and harvester state.
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8787/health"
|
curl -s "http://localhost:8787/health" | jq
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response:** `ok`
|
**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
|
## MCP Integration
|
||||||
|
|
||||||
|
|
@ -113,9 +177,9 @@ The API implements the Model Context Protocol (MCP) specification, allowing AI a
|
||||||
The following tools are exposed via MCP:
|
The following tools are exposed via MCP:
|
||||||
|
|
||||||
1. **get-random**: Generate random bytes (cryptographically secure)
|
1. **get-random**: Generate random bytes (cryptographically secure)
|
||||||
3. **get-stream**: Stream random bytes continuously
|
2. **get-stream**: Stream random bytes continuously
|
||||||
4. **list-cameras**: Discover available cameras
|
3. **list-cameras**: Discover available cameras
|
||||||
5. **health-check**: Verify server status
|
4. **health-check**: Verify server status
|
||||||
|
|
||||||
### Self-Referencing URLs
|
### Self-Referencing URLs
|
||||||
|
|
||||||
|
|
@ -135,50 +199,83 @@ This ensures URLs in the MCP response always reference the correct origin, wheth
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
# Get 32 random bytes
|
# Get 32 random bytes
|
||||||
response = requests.get("http://localhost:8787/random?bytes=32")
|
resp = requests.get("http://localhost:8787/random?bytes=32")
|
||||||
random_bytes = response.content
|
random_bytes = resp.content
|
||||||
|
print(random_bytes.hex())
|
||||||
|
|
||||||
# Get hex string
|
# Stream random data
|
||||||
response = requests.get("http://localhost:8787/random?bytes=64&hex=true")
|
with requests.get("http://localhost:8787/stream?hex=true", stream=True) as r:
|
||||||
hex_string = response.text
|
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/Node.js
|
||||||
```javascript
|
```javascript
|
||||||
// Get random bytes
|
// Get random bytes
|
||||||
const response = await fetch("http://localhost:8787/random?bytes=32");
|
const resp = await fetch("http://localhost:8787/random?bytes=32");
|
||||||
const buffer = await response.arrayBuffer();
|
const buffer = await resp.arrayBuffer();
|
||||||
const bytes = new Uint8Array(buffer);
|
const bytes = new Uint8Array(buffer);
|
||||||
|
|
||||||
// Stream random data
|
// Stream random data
|
||||||
const stream = await fetch("http://localhost:8787/stream?bytes=1024");
|
const stream = await fetch("http://localhost:8787/stream?hex=true");
|
||||||
const reader = stream.body.getReader();
|
const reader = stream.body.getReader();
|
||||||
// ... read chunks
|
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
|
### curl (comprehensive)
|
||||||
```bash
|
```bash
|
||||||
# Basic usage
|
# ── Random ────────────────────────────────────────────
|
||||||
curl "http://localhost:8787/random?bytes=32&hex=true"
|
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
|
||||||
|
|
||||||
# Save to file
|
# ── Stream ────────────────────────────────────────────
|
||||||
curl "http://localhost:8787/random?bytes=1024" -o random.bin
|
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
|
||||||
|
|
||||||
# Stream
|
# ── Tools ─────────────────────────────────────────────
|
||||||
curl -N "http://localhost:8787/stream"
|
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
|
## Limitations
|
||||||
|
|
||||||
- Maximum 1MB per request (`/random`)
|
- Maximum 1 MB per request (`/random`)
|
||||||
- Maximum 4 concurrent requests
|
- Maximum 4 concurrent requests
|
||||||
- Requires a camera device with covered lens
|
- Requires a camera device with covered lens
|
||||||
- Performance depends on camera frame rate
|
- Performance depends on camera frame rate
|
||||||
|
- CSPRNG fallback is used when the camera pool is empty (still cryptographically safe, but not quantum)
|
||||||
|
|
||||||
## Security Notes
|
## Security Notes
|
||||||
|
|
||||||
- No authentication required (intended for local/trusted networks)
|
- No authentication required (intended for local/trusted networks)
|
||||||
- Random data is cryptographically secure when using `/random` endpoint
|
- Random data is cryptographically secure from both the camera entropy pool and ChaCha20 CSPRNG fallback
|
||||||
|
- The CSPRNG is periodically re-seeded with real camera entropy
|
||||||
- Consider rate limiting in production deployments
|
- Consider rate limiting in production deployments
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
|
||||||
154
src/index.html
154
src/index.html
|
|
@ -546,22 +546,145 @@
|
||||||
const hexParam = fmt === 'hex' ? '&hex=true' : '';
|
const hexParam = fmt === 'hex' ? '&hex=true' : '';
|
||||||
const url = `${origin}/random?bytes=${bytes}${hexParam}`;
|
const url = `${origin}/random?bytes=${bytes}${hexParam}`;
|
||||||
|
|
||||||
document.getElementById('code-curl').textContent = fmt === 'raw'
|
// ── cURL ──────────────────────────────────────────────────
|
||||||
? `# Get ${bytes} raw random bytes\ncurl -s "${origin}/random?bytes=${bytes}" -o random.bin\n\n# Or pipe to xxd for viewing\ncurl -s "${origin}/random?bytes=${bytes}" | xxd`
|
const curlRandom = fmt === 'raw'
|
||||||
|
? `# Get ${bytes} raw random bytes\ncurl -s "${origin}/random?bytes=${bytes}" -o random.bin\n\n# Pipe to xxd for hex viewing\ncurl -s "${origin}/random?bytes=${bytes}" | xxd`
|
||||||
: `# Get ${bytes} random bytes as ${fmt}\ncurl -s "${url}"`;
|
: `# Get ${bytes} random bytes as ${fmt}\ncurl -s "${url}"`;
|
||||||
|
|
||||||
document.getElementById('code-python').textContent = fmt === 'raw'
|
const curlStream = [
|
||||||
? `import requests\n\nresp = requests.get("${origin}/random?bytes=${bytes}")\nrandom_bytes = resp.content # ${bytes} bytes\nprint(random_bytes.hex())`
|
`# ── Stream ──────────────────────────────────────────`,
|
||||||
: `import requests\n\nresp = requests.get("${url}")\nrandom_${fmt} = resp.text\nprint(random_${fmt})`;
|
`# Stream continuous random bytes (binary)`,
|
||||||
|
`curl -N "${origin}/stream"`,
|
||||||
document.getElementById('code-js').textContent = fmt === 'raw'
|
``,
|
||||||
? `const resp = await fetch("${origin}/random?bytes=${bytes}");\nconst buffer = await resp.arrayBuffer();\nconst bytes = new Uint8Array(buffer); // ${bytes} bytes\nconsole.log([...bytes].map(b => b.toString(16).padStart(2,'0')).join(''));`
|
`# Stream 1 KB as hex`,
|
||||||
: `const resp = await fetch("${url}");\nconst random = await resp.text();\nconsole.log(random);`;
|
`curl -N "${origin}/stream?bytes=1024&hex=true"`,
|
||||||
|
``,
|
||||||
document.getElementById('code-rust').textContent = `use reqwest;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n let bytes = reqwest::get("${url}")\n .await?.${fmt === 'raw' ? 'bytes' : 'text'}().await?;\n println!("{:?}", bytes);\n Ok(())\n}`;
|
`# Stream unlimited hex to a file`,
|
||||||
|
`curl -N "${origin}/stream?hex=true" > entropy.hex`,
|
||||||
document.getElementById('code-go').textContent = `package main\n\nimport (\n "fmt"\n "io"\n "net/http"\n)\n\nfunc main() {\n resp, _ := http.Get("${url}")\n defer resp.Body.Close()\n body, _ := io.ReadAll(resp.Body)\n fmt.Println(string(body))\n}`;
|
].join('\n');
|
||||||
|
|
||||||
|
const curlTools = [
|
||||||
|
`# ── Tools ───────────────────────────────────────────`,
|
||||||
|
`# Roll 3d20`,
|
||||||
|
`curl -s "${origin}/dice?d=20&count=3"`,
|
||||||
|
``,
|
||||||
|
`# Generate a 24-char password (full charset)`,
|
||||||
|
`curl -s "${origin}/password?length=24&charset=full"`,
|
||||||
|
``,
|
||||||
|
`# Flip a quantum coin`,
|
||||||
|
`curl -s "${origin}/coin"`,
|
||||||
|
``,
|
||||||
|
`# Shake the Quantum 8 Ball`,
|
||||||
|
`curl -s "${origin}/8ball?question=Will+it+work"`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
const curlHealth = [
|
||||||
|
`# ── Health & Discovery ───────────────────────────────`,
|
||||||
|
`curl -s "${origin}/health" | jq`,
|
||||||
|
`curl -s "${origin}/cameras" | jq`,
|
||||||
|
`curl -s "${origin}/.well-known/mcp.json" | jq`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
document.getElementById('code-curl').textContent =
|
||||||
|
curlRandom + '\n\n' + curlStream + '\n\n' + curlTools + '\n\n' + curlHealth;
|
||||||
|
|
||||||
|
// ── Python ────────────────────────────────────────────────
|
||||||
|
const pyRandom = fmt === 'raw'
|
||||||
|
? `import requests\n\n# Random bytes\nresp = requests.get("${origin}/random?bytes=${bytes}")\nrandom_bytes = resp.content # ${bytes} bytes\nprint(random_bytes.hex())`
|
||||||
|
: `import requests\n\n# Random bytes\nresp = requests.get("${url}")\nprint(resp.text)`;
|
||||||
|
|
||||||
|
const pyStream = [
|
||||||
|
`\n# Stream random data`,
|
||||||
|
`with requests.get("${origin}/stream?hex=true", stream=True) as r:`,
|
||||||
|
` for chunk in r.iter_content(chunk_size=64):`,
|
||||||
|
` print(chunk.decode(), end="")`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
const pyTools = [
|
||||||
|
`\n# Dice / Password / Coin / 8 Ball`,
|
||||||
|
`print(requests.get("${origin}/dice?d=6&count=5").json())`,
|
||||||
|
`print(requests.get("${origin}/password?length=20").json()["password"])`,
|
||||||
|
`print(requests.get("${origin}/coin").json()["result"])`,
|
||||||
|
`print(requests.get("${origin}/8ball").json()["answer"])`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
document.getElementById('code-python').textContent =
|
||||||
|
pyRandom + '\n\n' + pyStream + '\n\n' + pyTools;
|
||||||
|
|
||||||
|
// ── JavaScript ────────────────────────────────────────────
|
||||||
|
const jsRandom = fmt === 'raw'
|
||||||
|
? `// Random bytes\nconst resp = await fetch("${origin}/random?bytes=${bytes}");\nconst buf = new Uint8Array(await resp.arrayBuffer());\nconsole.log([...buf].map(b => b.toString(16).padStart(2,'0')).join(''));`
|
||||||
|
: `// Random bytes\nconst resp = await fetch("${url}");\nconsole.log(await resp.text());`;
|
||||||
|
|
||||||
|
const jsStream = [
|
||||||
|
`\n// Stream random data`,
|
||||||
|
`const stream = await fetch("${origin}/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));`,
|
||||||
|
`}`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
const jsTools = [
|
||||||
|
`\n// Dice / Password / Coin / 8 Ball`,
|
||||||
|
`const dice = await (await fetch("${origin}/dice?d=20&count=3")).json();`,
|
||||||
|
`const pw = await (await fetch("${origin}/password?length=24&charset=full")).json();`,
|
||||||
|
`const coin = await (await fetch("${origin}/coin")).json();`,
|
||||||
|
`const ball = await (await fetch("${origin}/8ball")).json();`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
document.getElementById('code-js').textContent =
|
||||||
|
jsRandom + '\n\n' + jsStream + '\n\n' + jsTools;
|
||||||
|
|
||||||
|
// ── Rust ──────────────────────────────────────────────────
|
||||||
|
document.getElementById('code-rust').textContent = [
|
||||||
|
`use reqwest;`,
|
||||||
|
``,
|
||||||
|
`#[tokio::main]`,
|
||||||
|
`async fn main() -> Result<(), Box<dyn std::error::Error>> {`,
|
||||||
|
` // Random bytes`,
|
||||||
|
` let data = reqwest::get("${url}")`,
|
||||||
|
` .await?.${fmt === 'raw' ? 'bytes' : 'text'}().await?;`,
|
||||||
|
` println!("{:?}", data);`,
|
||||||
|
``,
|
||||||
|
` // Stream (reads chunks until server closes)`,
|
||||||
|
` let mut stream = reqwest::get("${origin}/stream?bytes=1024&hex=true")`,
|
||||||
|
` .await?;`,
|
||||||
|
` while let Some(chunk) = stream.chunk().await? {`,
|
||||||
|
` print!("{}", String::from_utf8_lossy(&chunk));`,
|
||||||
|
` }`,
|
||||||
|
` Ok(())`,
|
||||||
|
`}`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
// ── Go ────────────────────────────────────────────────────
|
||||||
|
document.getElementById('code-go').textContent = [
|
||||||
|
`package main`,
|
||||||
|
``,
|
||||||
|
`import (`,
|
||||||
|
` "fmt"`,
|
||||||
|
` "io"`,
|
||||||
|
` "net/http"`,
|
||||||
|
` "os"`,
|
||||||
|
`)`,
|
||||||
|
``,
|
||||||
|
`func main() {`,
|
||||||
|
` // Random bytes`,
|
||||||
|
` resp, _ := http.Get("${url}")`,
|
||||||
|
` body, _ := io.ReadAll(resp.Body)`,
|
||||||
|
` resp.Body.Close()`,
|
||||||
|
` fmt.Println(string(body))`,
|
||||||
|
``,
|
||||||
|
` // Stream (reads until EOF or byte limit)`,
|
||||||
|
` sr, _ := http.Get("${origin}/stream?bytes=1024&hex=true")`,
|
||||||
|
` defer sr.Body.Close()`,
|
||||||
|
` io.Copy(os.Stdout, sr.Body)`,
|
||||||
|
`}`,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
document.getElementById('mcp-url').href = origin + '/.well-known/mcp.json';
|
document.getElementById('mcp-url').href = origin + '/.well-known/mcp.json';
|
||||||
document.getElementById('mcp-url').textContent = origin + '/.well-known/mcp.json';
|
document.getElementById('mcp-url').textContent = origin + '/.well-known/mcp.json';
|
||||||
document.getElementById('code-mcp').textContent = `curl -s "${origin}/.well-known/mcp.json" | jq`;
|
document.getElementById('code-mcp').textContent = `curl -s "${origin}/.well-known/mcp.json" | jq`;
|
||||||
|
|
@ -572,6 +695,7 @@
|
||||||
updateCodeExamples();
|
updateCodeExamples();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Click-to-copy for output boxes
|
// Click-to-copy for output boxes
|
||||||
const copyToast = document.getElementById('copy-toast');
|
const copyToast = document.getElementById('copy-toast');
|
||||||
let copyTimeout;
|
let copyTimeout;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue