Skip to main content
Glama
README.md
# Streamfog MCP

<p align="center">
  <a href="https://github.com/casey/just"><img src="https://img.shields.io/badge/just-ready_to_go-7c5cfc?style=flat-square&logo=just&logoColor=white" alt="Just"></a>
  <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
  <a href="https://python.org"><img src="https://img.shields.io/badge/Python-3.12+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"></a>
  <a href="https://biomejs.dev"><img src="https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat-square&logo=biome&logoColor=white" alt="Biome"></a>
  <a href="https://github.com/PrefectHQ/fastmcp"><img src="https://img.shields.io/badge/FastMCP-3.4-7c5cfc?style=flat-square" alt="FastMCP"></a>
</p>


> πŸ“– **[Installation Guide](INSTALL.md)** β€” quick start, manual setup, and troubleshooting
> πŸ“– **[Docs](docs/)** β€” [Configuration](docs/CONFIGURATION.md) Β· [Tools](docs/TOOLS.md) Β· [Troubleshooting](docs/TROUBLESHOOTING.md) Β· [Development](docs/DEVELOPMENT.md)
> πŸ€– **[llms-full.txt](llms-full.txt)** β€” full LLM-readable documentation

**AI-driven AR lens orchestrator for live OBS streams.** Control Streamfog face filters, AR effects, and Vtuber avatars through MCP tools via the local Streamer.bot WebSocket bridge. Your AI assistant becomes a stream producer.

## What is Streamfog?

**Streamfog** is a Windows desktop app (https://streamfog.com) that streamers
use to put AR effects on their face during live broadcasts β€” face filters
("beauty smooth", "cyber helmet"), animated lenses, background effects, and
Vtuber-style avatars. It takes your webcam feed, applies the effect in real
time, and renders the result into OBS Studio through a browser source.

Two things matter for automation:

1. **Streamfog has no public API, CLI, or plugin SDK.** You cannot script it
   directly, and it cannot tell you which lens is active. It is effectively
   a black box that only listens to Streamer.bot.
2. **Streamer.bot is the remote control.** [Streamer.bot](https://streamer.bot)
   is a free automation tool for streamers. Streamfog registers itself with
   Streamer.bot as an integration, and Streamer.bot exposes a local
   WebSocket server that accepts `DoAction` commands by name (e.g. fire the
   action `SetLens_BeautySmooth`).

**This project is the bridge between the two**: it gives an AI assistant (or
the dashboard, or any script) a clean tool interface β€” `streamfog_set_lens`,
`streamfog_clear_effects`, `streamfog_toggle_avatar`, `streamfog_status`,
`streamfog_list_lenses` β€” and translates each call into a Streamer.bot
`DoAction` dispatch. Without this server you would have to open Streamer.bot
and click actions manually; with it, your agent becomes a stream producer.

> ⚠️ **Fire-and-forget**: Streamer.bot does not report whether an action
> succeeded, and Streamfog cannot be queried. A tool returning "success"
> means *dispatched*, not *applied* β€” confirm visually on the stream.

| | |
|--:|--|
| **You might use this if…** | You want your AI to switch AR lenses, toggle Vtuber avatars, or clear effects during live OBS broadcasts β€” controlled by Twitch chat events, channel points, or agentic automation. |
| **What it connects to** | [Streamfog](https://streamfog.com) desktop app β†’ [Streamer.bot](https://streamer.bot) WebSocket β†’ this MCP server |
| **Ports** | Backend **10994**, Dashboard **10995** |
| **Start** | `just bootstrap` then `start.ps1` |

## How to use this server (3 steps)

1. **Install the two external apps** (one-time): Streamfog + Streamer.bot,
   enable Streamfog's integration inside Streamer.bot, and enable
   Streamer.bot's WebSocket server on port 8080. Full walkthrough:
   [docs/ONBOARDING.md](docs/ONBOARDING.md).
2. **Map your lenses**: create `lenses.json` linking human-readable lens
   names to the exact Streamer.bot action names that apply them (see
   [Lens Map](#lens-map-lensesjson)).
3. **Start and drive it**: `start.ps1` boots the backend + dashboard; then
   either connect your MCP client (Claude Desktop / Cursor / opencode) over
   stdio or `http://127.0.0.1:10994/mcp`, click lenses on the dashboard, or
   call the REST API from scripts. All three surface the same bridge.

## Architecture

Plain English: **your AI talks to this server, this server talks to
Streamer.bot, Streamer.bot tells Streamfog what to render, and OBS shows the
result.** Every hop is local.

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     MCP            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     WebSocket      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  LLM Agent  β”‚ ───────────────→  β”‚  streamfog-mcp   β”‚ ────────────────→ β”‚ Streamer.bot  β”‚
β”‚  (Claude,   β”‚ ←───────────────  β”‚  :10994 (FastMCP) β”‚ ←──────────────── β”‚ :8080         β”‚
β”‚   Gemini)   β”‚   stdio / /mcp    β”‚  :10995 (React)   β”‚   DoAction JSON   β”‚               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                                β”‚ Native Hook
                                                                         β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                                                         β”‚  Streamfog    β”‚
                                                                         β”‚  Desktop App  β”‚
                                                                         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                                β”‚ Browser Source
                                                                         β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                                                         β”‚  OBS Studio   β”‚
                                                                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

- **MCP tools** (for AI agents): served over stdio or the streamable HTTP
  endpoint at `http://127.0.0.1:10994/mcp`.
- **REST API** (for scripts + dashboard): `/api/*` on the same port, backed
  by the same bridge instance.
- **Dashboard** (for humans): React SPA at `:10995` β€” lens grid, status
  KPIs, chat, logs.

The MCP endpoint is served at `http://127.0.0.1:10994/mcp` (streamable HTTP)
in dual mode, alongside the REST API and dashboard.

## Quick Start

```powershell
uv sync
# Edit lenses.json with your Streamer.bot action names
# Set STREAMFOG_MCP_STREAMERBOT_TOKEN in .env if using auth
.\start.ps1
```

MCP-only via stdio (for Cursor, Claude Desktop):

```powershell
uv run -m streamfog_mcp --stdio
```

## Prerequisites

1. [Streamfog](https://streamfog.com) installed and running
2. [Streamer.bot](https://streamer.bot) installed and running
3. Streamfog β†’ Streamer.bot integration enabled in Streamfog's Integrations panel
4. Streamer.bot WebSocket server enabled (Settings β†’ WebSocket Server)
5. Actions created in Streamer.bot (e.g. `SetLens_BeautySmooth`, `ClearEffects`, `ToggleAvatar`)
6. `lenses.json` populated with your action→lens mappings

See [docs/ONBOARDING.md](docs/ONBOARDING.md) for the step-by-step walkthrough.

## Configuration

| Variable | Default | Description |
|----------|---------|-------------|
| `STREAMFOG_MCP_STREAMERBOT_HOST` | `127.0.0.1` | Streamer.bot WebSocket host |
| `STREAMFOG_MCP_STREAMERBOT_PORT` | `8080` | Streamer.bot WebSocket port |
| `STREAMFOG_MCP_STREAMERBOT_TOKEN` | β€” | Streamer.bot auth token |
| `STREAMFOG_MCP_LENS_MAP_PATH` | `lenses.json` | Path to lens→action mapping file |
| `STREAMFOG_MCP_PORT` | `10994` | Backend port |
| `STREAMFOG_MCP_LOG_LEVEL` | `INFO` | Logging level |

## Lens Map (`lenses.json`)

```json
{
  "beauty_smooth": "SetLens_BeautySmooth",
  "cyber_helmet": "SetLens_CyberHelmet",
  "vtuber_avatar": "SetLens_VTuberAvatar"
}
```

Keys are human-readable lens identifiers used in MCP tool calls. Values are the corresponding Streamer.bot action names. Keys starting with `_` are ignored; unknown identifiers fall back to the action `SetLens_{identifier}`.

## MCP Tools (5)

### Lens Control
| Tool | Description |
|------|-------------|
| `streamfog_set_lens` | Activate a specific AR lens or face filter |
| `streamfog_clear_effects` | Strip all effects, return camera to baseline |
| `streamfog_toggle_avatar` | Toggle Vtuber-style avatar on/off |

### Discovery β€” READ_ONLY
| Tool | Description |
|------|-------------|
| `streamfog_list_lenses` | List all configured lenses from lenses.json |
| `streamfog_status` | Bridge connection health + lens count |

## REST API

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/health` | GET | Liveness probe (status, version, uptime, tool count, bridge) |
| `/api/v1/status` | GET | Server + bridge health |
| `/api/v1/lenses` | GET | List all lenses |
| `/api/v1/lenses/set` | POST | Activate a lens (`{"lens_identifier": "beauty_smooth"}`) |
| `/api/v1/lenses/reload` | POST | Reload lens map from disk |
| `/api/v1/effects/clear` | POST | Clear all effects |
| `/api/v1/avatar/toggle` | POST | Toggle avatar |
| `/api/tools` | GET | Dynamic MCP tool list with schemas |
| `/api/capabilities` | GET | Capability discovery |
| `/api/skills` | GET | Skill list |
| `/api/skills/{name}` | GET | Skill content (markdown) |
| `/api/llm/discover` | GET | Local LLM provider probe (Ollama/LM Studio/vLLM) + GPU |
| `/api/logs` | GET | Ring-buffer log window |
| `/api/v1/diagnostics` | GET | Tool list, system info, errors |

## Web Dashboard

Dark SOTA dashboard at `:10995` (React + Vite + Tailwind + Zustand):

- **Dashboard** β€” hero + KPI cards (server, tools, bridge, uptime), lens grid, quick actions, exponential-backoff health
- **Tools** β€” dynamic tool list with schemas from `/api/tools`
- **Chat** β€” skill-first local LLM chat (Ollama/LM Studio/vLLM), 4 personalities, localStorage history, export
- **Settings** β€” backend health + LLM provider detection
- **Help** β€” architecture, env reference, troubleshooting
- **Logs** β€” live ring-buffer modal (Ctrl+L)

Keyboard: Ctrl+Scroll zoom, Ctrl+0 reset, Ctrl+L logs.

## Project Structure

```
streamfog-mcp/
β”œβ”€β”€ src/streamfog_mcp/
β”‚   β”œβ”€β”€ _mcp.py              FastMCP singleton + resources
β”‚   β”œβ”€β”€ server.py            FastAPI gateway (REST + /mcp mount)
β”‚   β”œβ”€β”€ __main__.py          CLI entry (--stdio / --serve)
β”‚   β”œβ”€β”€ config.py            Pydantic settings (STREAMFOG_MCP_ prefix)
β”‚   β”œβ”€β”€ errors.py            _error_response() with logger.exception
β”‚   β”œβ”€β”€ logging_ring.py      Ring buffer for /api/logs
β”‚   β”œβ”€β”€ skills/streamfog/    SKILL.md (chat preprompt)
β”‚   β”œβ”€β”€ tools/core_tools.py  5 @mcp.tool() decorators
β”‚   └── services/streamerbot.py  Streamer.bot WebSocket client
β”œβ”€β”€ webapp/                  Vite + React 19 + Tailwind + Zustand
β”œβ”€β”€ native/                  Tauri 2.0 desktop wrapper
β”œβ”€β”€ lenses.json              Lens β†’ action mapping
β”œβ”€β”€ pyproject.toml / uv.lock
β”œβ”€β”€ start.ps1 / start.bat
β”œβ”€β”€ justfile
└── tests/                   13 tests (units + endpoint + e2e)
```

## Verification

```powershell
just lint          # ruff
just test          # pytest (coverage-gated)
uv run pyright src/  # types
cd webapp && bun run check && bun run biome:ci
cd webapp && bunx playwright test   # e2e
```

## Known Limitations

- Streamfog does not expose a native CLI or local API β€” all control goes through Streamer.bot
- Lens activation is fire-and-forget (Streamer.bot does not report success/failure for actions)
- No lens preview or thumbnail retrieval (Streamfog desktop is a black box)
- Lumia/Crowd Control bridge path is documented but not yet implemented as an alternative transport

TDQS

A4.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct operation: status checks connectivity, set_lens activates a specific lens, clear_effects removes all effects, toggle_avatar toggles the avatar overlay, and list_lenses enumerates available lenses. There is no functional overlap.

Naming Consistency5/5

All tool names follow a consistent streamfog_verb_noun pattern using snake_case. Verbs are descriptive and uniform, making it easy to predict tool behavior from the name.

Tool Count5/5

Five tools is well-scoped for an AR lens management server. Each tool serves a core function: status, set lens, clear effects, toggle avatar, and list lenses, without unnecessary duplication.

Completeness4/5

The tool set covers essential operations for managing AR lenses, including status checking, activation, clearing, avatar toggling, and listing. A minor gap is the lack of a tool to get the currently active lens or avatar state, though status provides bridge health.

Maintenance

ActivityMaintained
ResponsivenessNo issues