Skip to main content
Glama
README.md
# jev-av-analysis-mcp

> πŸ‡¨πŸ‡³ [δΈ­ζ–‡ζ–‡ζ‘£](README.zh-CN.md)

> Local-first, zero-key structured audio/video analysis: **download β†’ transcribe β†’ decide** in one pipeline.
> Transcription runs on your own machine with yt-dlp + whisper.cpp; analysis uses [TypeSafe Jev](https://typesafe.ai) (System One decision model) to emit **structured labels**, not prose.

An MCP server that turns any video/audio into "transcript + structured analysis": topic tags, sentiment tone,
sensitivity flags (profanity / violence / medical advice / financial advice / politics / copyrighted music / harassment), and a **publish gate**
(publish / review / block). Built for podcasters, video creators, YouTubers β€” anyone who wants an agent to auto-tag and screen their content.

```
npm install && npm run build
node dist/index.js doctor      # print transcription deps + Jev mode diagnostics
```

Connect `node dist/index.js` in your MCP client and use the four tools below.

---

## The four tools

| Tool | Purpose |
|---|---|
| `transcribe_media` | URL or local file β†’ transcript (URL via yt-dlp, local/downloaded via whisper.cpp) |
| `fetch_media` | Use yt-dlp to pull the best audio track of a video/audio to local; returns path + title + duration |
| `transcribe_file` | Local audio/video file β†’ transcript |
| `analyze_transcript` | Transcript β†’ Jev structured analysis (see below) |

`analyze_transcript` takes a piece of text (usually from the three transcription tools above) and returns:

```json
{
  "topics":            { "tech": 0.9, "business": 0.1, "education": 0.3, "...": 0.0 },
  "dominant_topics":   ["tech"],
  "sentiment":         { "score": 3, "label": "positive", "confidence": 0.8, "probabilities": {"0":0,"1":0,"2":0.1,"3":0.8,"4":0.1} },
  "sensitivity":       { "profanity": 0.1, "violence": 0.0, "medical_advice": 0.2, "financial_advice": 0.9, "...": 0.0 },
  "flagged_sensitivity": ["financial_advice"],
  "has_key_claims":    0.8,
  "has_engagement_hook": 0.4,
  "publish_gate":      "review",
  "confidence":        0.8,
  "mocked":            false
}
```

**Fields**
| Field | Meaning |
|---|---|
| `topics` / `dominant_topics` | Membership probabilities over 8 default topics (>0.5 β†’ dominant); override via `categories` |
| `sentiment` | 5-level ordinal: very_negative β†’ very_positive, with distribution and confidence |
| `sensitivity` / `flagged_sensitivity` | Probabilities over 7 sensitivity classes; >0.7 β†’ flagged |
| `has_key_claims` | Whether it contains factual claims that need verification (noul probability) |
| `has_engagement_hook` | Whether the opening has a strong hook (good for short-form clips) |
| `publish_gate` | `publish` / `review` / `block` (see gate logic) |
| `confidence` | Calibrated confidence of the sentiment dimension |

**publish_gate gate logic**
- `publish`: no sensitivity class > 0.7
- `review`: a sensitivity class in 0.7–0.9 β†’ human review before publishing
- `block`: any sensitivity class > 0.9 β†’ high risk, block

> ⚠️ **Capability boundary (important)**: Jev is a decision model β€” it **labels / scores**, it does not write section headings or summaries.
> Do chapter segmentation and summarization yourself based on the transcript `segments` (or plug in a separate generative model). Before any publishing action,
> check `publish_gate` + `confidence` first β€” **do not** auto-publish just because one probability is high.

---

## Zero-key / local-first

- **Transcription layer**: `MEDIA_MCP_MOCK=1` β†’ skip yt-dlp/whisper and return an offline stub (zero-config for CI/demos).
  Real mode requires `yt-dlp` and a compiled `whisper.cpp` on your machine, plus `WHISPER_MODEL_PATH` configured.
- **Decision layer**: no `TYPESAFE_API_KEY` β†’ automatic Jev mock mode (deterministic offline stub); set it β†’ call the real API.

**Environment variables**
| Variable | Default | Description |
|---|---|---|
| `TYPESAFE_API_KEY` | β€” | Required for real Jev calls; blank falls back to mock |
| `JEV_MCP_MOCK` | `0` | `1` forces Jev mock |
| `MEDIA_MCP_MOCK` | `0` | `1` skips transcription binaries |
| `YT_DLP_BIN` / `WHISPER_BIN` | `yt-dlp` / `whisper-cli` | Binary paths |
| `WHISPER_MODEL_PATH` | β€” | Absolute path to the `.ggml` model file |
| `WHISPER_MODEL` | `base.en` | Model name hint |
| `MEDIA_MCP_TIMEOUT_MS` | `600000` | Transcription timeout |

**Install engines locally (real transcription)**
```bash
pip install yt-dlp
git clone https://github.com/ggerganov/whisper.cpp && cd whisper.cpp && make
# download a small model, e.g.:
bash ./models/download-ggml-model.sh base.en
export WHISPER_MODEL_PATH="$PWD/models/ggml-base.en.bin"
```

---

## Extremely low cost

Transcription runs on your own machine (CPU/GPU, zero call fees); decisions are a single Jev call, tens of thousands of tokens per call.
There's no token-usage chart because it's already cheap β€” think of it as "one cheap gate in your content pipeline".

---

## Tests

```bash
npm test     # smoke + MCP protocol handshake (dual mock mode, no key needed)
```

---

## License

MIT

TDQS

A3.7/5.0

Scored across 4 tools

Disambiguation3/5

transcribe_media and transcribe_file overlap for local files, and transcribe_media already handles URL fetching that fetch_media also provides. However, the descriptions make each tool's primary role fairly clear: fetch_media is download-only, transcribe_file is local-only, and transcribe_media is the all-in-one path.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: transcribe_media, fetch_media, transcribe_file, analyze_transcript. The naming is predictable and easy to navigate.

Tool Count4/5

Four tools is a reasonable size for this audio/video analysis pipeline. The count is only slightly higher than necessary because transcribe_file is mostly redundant with transcribe_media, but it is not bloated.

Completeness5/5

The server covers the full workflow: fetch media, transcribe it, and analyze the transcript with the Jev model. There are no obvious missing operations for the stated AV-analysis purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues