Skip to main content
Glama
README.md
# kbk-mcp

MCP-Server für **KaboomKartell** — bringt das KBK-Radio in jede MCP-fähige KI
(Claude, ChatGPT, Perplexity …). Bind die URL einmal als Connector ein, dann
reicht „guck mal auf KBK was läuft".

Öffentlicher Endpoint (nach Deploy): **`https://mcp.kaboomkartell.com/mcp`**

## Tools (13 read-only + `vote_track` write + 1 App-Tool)

| Tool | Was |
|---|---|
| `get_now_playing` | Live-Track je Channel (phonk/hardtek) + nächster Track |
| `list_channels` | Echte Struktur: 2 Channels, 4 Genres, Mapping, Akzentfarben |
| `get_crowd_control` | Die 5 Vote-Kandidaten + Live-Tally (read-only) |
| `get_schedule` / `get_next_drop` | Timetable + nächster Drop |
| `search_tracks` / `get_track` | Library-Suche + Track-Details |
| `list_playlists` / `get_playlist` | Playlists + ihre Tracks |
| `get_stats` | Live-Zahlen (wolves online, tracks spun, BPM, aura) |
| `get_twitch_status` | Twitch-Live-Status |
| `get_live_alert` | Zeitkritischer Live-Trigger (Twitch on air / nächstes Event) — einziger Anlass für eine proaktive Erinnerung |
| `get_multiverse` | Kanon des Song-Multiversums als Möglichkeitsraum (Kosmologie + Regeln + versiegelte Zonen) — proxied `GET /api/kbk/canon` der Website |
| **`vote_track`** | **(write)** Vote fürs nächste Lied (Crowd Control) mit Agenten-Token; ohne Token → Ein-Klick-Authorize-Link statt Fehler |
| **`play_channel`** | **Öffnet das interaktive Player-Widget** (MCP-App) und spielt den Live-Stream (Klick auf Play) |

## Architektur

- `src/kbk-client.ts` — einzige Kopplungsschicht zu den öffentlichen KBK-APIs.
- `src/tools.ts` — Registry der 13 read-only Tools (inkl. `get_multiverse`) + `vote_track` (write).
- `src/player-app.ts` — `play_channel` + UI-Resource (MCP-App).
- `src/server.ts` — `createServer()` (transport-agnostisch).
- `src/main.ts` — **stdio**-Entry (lokal/Claude Desktop).
- `src/http.ts` — **Streamable HTTP**-Entry (remote, `/mcp` + `/health`, Rate-Limit).
- `src/ui/` — Player-Widget (vite → `dist/ui/index.html`, Single-File).

**Daten-URLs:** Tools rufen KBK intern (`KBK_BASE_URL`, auf dem Server
`127.0.0.1:8081`); Stream-/Cover-URLs werden auf die öffentliche Domain
(`KBK_PUBLIC_URL`) umgeschrieben, damit der Browser sie laden kann.

## Entwicklung

```bash
npm install
npm run build        # tsc (server) + vite (player-ui)
npm run smoke        # stdio-Test gegen Live-API (15 Tools + Player-Resource)
npm run smoke:http   # HTTP-Test (Streamable HTTP)
```

## Lokal in Claude Desktop (stdio)

`%APPDATA%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "kbk": {
      "command": "C:\\Program Files\\nodejs\\node.exe",
      "args": ["C:\\…\\kbk-mcp\\dist\\main.js"]
    }
  }
}
```

## Öffentlich nutzen (Remote-Connector)

Sobald deployt, fügt **jeder Nutzer** den Connector einmal in seiner KI hinzu:
- **Claude** (Free/Pro/Max/Team/Enterprise): Settings → Connectors → Custom →
  URL `https://mcp.kaboomkartell.com/mcp`.
- **ChatGPT** (Pro + Developer Mode), **Perplexity** (Pro+): analog.

Danach: *„Was läuft gerade auf KaboomKartell?"* oder *„Mach den KBK-Player auf."*

## Deploy (`mcp.kaboomkartell.com`)

Ein Linux-Server, Port **8086**, hinter Caddy. Artefakte in `deploy/`:
- `kbk-mcp.service` → `/etc/systemd/system/` (Port 8086, KBK_BASE_URL intern).
- `Caddyfile-snippet.txt` → Block in `/etc/caddy/Caddyfile` + `systemctl reload caddy`.
- `deploy.sh` → pull + `npm ci` + `npm run build` + restart + health-check.

Erst-Setup (einmalig, als root): Repo nach `/opt/kbk-mcp/repo` klonen,
systemd-Unit + Caddy-Block installieren, `systemctl enable --now kbk-mcp`.
Voraussetzung: die MCP-Domain ist per DNS propagiert. Updates danach via `deploy.sh`.

## Roadmap

- **Stufe 3:** Voting mit OAuth (Crowd-Control aktiv mitsteuern), `vote_next_track`.
- Härtetest: Ton beim Weiterchatten — Claude **und** ChatGPT.

## Tech

`@modelcontextprotocol/sdk` · `@modelcontextprotocol/ext-apps` · `express` 5 ·
`zod` 4 · `vite` + `vite-plugin-singlefile` · TypeScript (ESM).

TDQS

A4.2/5.0

Scored across 15 tools

Disambiguation4/5

Most tools are clearly distinct (search vs. playlist vs. schedule), but get_live_alert and get_twitch_status both report live status, and get_next_drop is essentially a subset of get_schedule. Descriptions are detailed enough to disambiguate, so no serious misselection risk.

Naming Consistency5/5

All tool names follow the consistent verb_noun pattern (get_, list_, search_, vote_, play_) with snake_case throughout. Actions are uniformly chosen (get for single items, list for collections), making the set predictable and easy to navigate.

Tool Count5/5

At 15 tools, the server stays within the ideal 3-15 range while covering the full breadth of the KBK platform: playback, channel info, track library, playlists, schedule, voting, stats, live status, and lore. Each tool fills a distinct need; there is no bloat.

Completeness5/5

The tool surface is comprehensive for a radio-consumer API: it covers what's playing, upcoming drops, track search and details, playlists, crowd control voting, live alerts, stats, and even the multiverse canon. It supports the user journey from discovery to listening to engagement. No obvious dead ends—read operations are paired with the necessary actions (e.g., get_crowd_control + vote_track).

Maintenance

ActivityStale
ResponsivenessNo issues