Sonicmatch MCP Server
io.github.js713-lab/sonicmatch-mcp
Analyze video mood and pace, then recommend license-safe BGM with mix specs and ffmpeg ducking.
What is the Sonicmatch MCP server?
Sonicmatch is an MCP server that analyzes video footage to recommend royalty-free and Creative Commons background music with proper licensing information. It watches the video itself—not the script—and returns ranked track suggestions, a hook window, beat-grid cuts, and ffmpeg ducking specifications for seamless mixing.
Sonicmatch bridges video editing and music selection by analyzing visual mood, energy curves, speech coverage, and scene cuts to recommend license-safe background music. Unlike script-based BGM tools, it ingests actual video files or URLs, understands the footage's pacing and tone, and outputs editor-ready mix specs with attribution and license details for every track. It works with seed catalogs, Jamendo, Freesound, and user-owned Artlist/Epidemic libraries—never scraping paid platforms.
How to install Sonicmatch
Copy-paste configuration for popular MCP clients.
GEMINI_API_KEYsecretOptional. Gemini video understanding for analyze_video_music.
JAMENDO_CLIENT_IDsecretOptional. Jamendo catalog search.
FREESOUND_API_KEYsecretOptional. Freesound beds and loops.
Tools & capabilities
Tools this server exposes to the agent.
ingest_video— Ingest a local video file or HTTPS URL and return an asset_id for analysis (no raw video bytes transmitted).analyze_video_music— Extract mood, energy curve, speech coverage, scene cuts, hook window, BPM, and search queries from video footage.recommend_bgm— Return 3–7 ranked license-safe tracks with mood/energy reasoning, license type, and attribution text.search_music— Free-text or BPM/mood search across seed catalog and optional Jamendo, Freesound, and user libraries.get_track— Retrieve one track's full metadata, license, attribution, preview URLs, and content-ID risk warnings.preview_mix— Trim hook, loop, apply optional speech ducking, and generate preview files plus ffmpeg command and mix spec.export_mix_spec— Output mix specification, ffmpeg recipe, and attribution text (optionally render if render=true).suggest_cuts— Snap scene cuts to a BPM grid and return EDL-style intro/peak/outro markers.generate_bed— Create a demo bed marked source=generated (requires i_understand_not_commercially_cleared=true; not cleared for ads).save_brand_kit— Persist BPM, mood, and no-vocals constraints for reuse across recommend_bgm calls.analyze_batch— Analyze up to 20 clips, cluster mood, and return a shared mini-playlist.status— Check ffmpeg availability, API keys, seed catalog count, and day-1 risk gates.
Use cases
- Score Instagram Reels and YouTube Shorts with mood-matched, license-safe background music and ducking specs.
- Batch-analyze product clips or travel vlogs and generate a shared playlist with consistent BPM and mood.
- Lock brand audio guidelines (BPM, no vocals) and apply them across multiple video projects.
- Export ffmpeg commands and mix specifications for CapCut, Premiere Pro, or DaVinci Resolve.
- Find royalty-free or Creative Commons music for ads and shops using user-owned Artlist or Epidemic Sound libraries.
Sonicmatch MCP server FAQ
Sonicmatch analyzes video footage to recommend license-safe background music. It watches the actual video—not a script—to understand mood, energy, pacing, and speech, then returns ranked tracks with proper licensing, a hook window, beat-grid suggestions, and ffmpeg ducking specs for mixing.
Yes. The code is MIT-licensed. It ships with a 20-track seed catalog of CC0 and CC-BY music. Optional integrations with Jamendo and Freesound are free (with API keys). For commercial music, you wire your own licensed Artlist or Epidemic Sound JSON—Sonicmatch does not scrape paid platforms.
For Claude Desktop: add sonicmatch to mcpServers in claude_desktop_config.json with command sonicmatch-mcp (after pip install git+https://github.com/js713-lab/sonic-match-mcp.git). For Cursor: add it to .cursor/mcp.json with uvx and the same git URL. See examples/claude_desktop.mcp.json and examples/cursor.mcp.json in the repo.
No. Sonicmatch works offline-ish with the seed catalog. Optional keys: GEMINI_API_KEY (for video understanding), JAMENDO_CLIENT_ID, FREESOUND_API_KEY. Platform URL ingest (YouTube, Instagram) requires SONICMATCH_ALLOW_YTDLP=1 and yt-dlp; local files are always preferred.
Sonicmatch recommends Creative Commons (CC0, CC-BY, CC-BY-NC) and royalty-free tracks. Every recommendation includes the license type and attribution text. Non-commercial (CC-BY-NC) tracks are never auto-recommended for ads. For commercial music, you must provide your own licensed Artlist or Epidemic Sound JSON.
Yes, via the generate_bed tool, but only if you set i_understand_not_commercially_cleared=true. Generated beds are marked source=generated and excluded from auto-recommendations because they are not cleared for ads or commercial use.
README (reference)
Source of truth, from the repository.
Sonicmatch
<!-- mcp-name: io.github.js713-lab/sonicmatch-mcp -->Video-native MCP server for license-safe BGM. Watches the footage — not the script — and returns a shortlist, a 12–20s hook, and an ffmpeg ducking spec.
<p align="center"> <img src="docs/banner.jpg" alt="Sonicmatch — video in, license-safe BGM out. Ingest, Analyze, Match, Mix." width="100%"> </p>Package / CLI: sonicmatch-mcp. A Model Context Protocol server for Claude Desktop, Cursor, and other MCP clients. Drop an Instagram Reel, YouTube Short, or TikTok-style clip. Get royalty-free / Creative Commons matches with the license printed on every row.
Video-to-BGM already exists. The wedge is not “I also match music”:
- it watches the footage, not the script
- it returns a hook window + ffmpeg ducking spec
- it is agent-native
- it prints the license instead of lying
Catalog quality will kill or save this. More tools will not.
Video or URL in
→ scene / mood / pace / speech analysis
→ license-safe BGM shortlist
+ beat/cut hints
+ optional mix preview
Do not treat this as “script in → YouTube Music search out.” That already exists (mcp-bgm-recommender). Sonicmatch watches the video.
| You own | You do not own |
|---|---|
| Local file / public URL ingest | Platform music licenses |
| Mood, energy curve, speech vs silence, scene cuts | Meta/TikTok “trending audio” graph |
| CC / royalty-free catalogs + optional paid adapters | Spotify / IG official libraries |
| Ranked tracks, preview URLs, mix spec, ffmpeg | Auto-publish to Instagram |
North star: ingest_video → analyze_video_music → recommend_bgm → preview_mix → export_mix_spec
License warning (read this)
- The code is MIT.
- Every track has its own license. It is printed on every recommendation.
- Nothing here is an official Instagram sticker, TikTok Commercial Music Library track, or YouTube Audio Library API result.
- Do not recommend commercial pop unless the adapter is explicitly a user-owned licensed library.
- CC-BY still needs attribution. CC-BY-NC is not ok for ads / shops. Non-commercial tracks are never auto-recommended.
- For ads / shops, wire a user-owned Artlist / Epidemic JSON (
examples/user_library.example.json). Do not scrape those sites. - Content ID can still hit you if you point at the wrong source. A CC label is not a waiver.
Demo
I dropped
./clip.mp4. Analyze it for an Instagram Reel and recommend 5 instrumental BGMs. Then mix the top pick with ducking and give me the ffmpeg command.
That prompt is the product. Install below, wire Claude Desktop or Cursor, paste it.
Quick start
Requires Python 3.10+ and ffmpeg / ffprobe on PATH. yt-dlp is optional and off by default (SONICMATCH_ALLOW_YTDLP=0) because platform extractors break and may violate ToS. Prefer a local file.
pip install git+https://github.com/js713-lab/sonic-match-mcp.git
sonicmatch-mcp # or: python3 -m sonicmatch
With uv, no clone:
uvx --from git+https://github.com/js713-lab/sonic-match-mcp.git sonicmatch-mcp
From a clone (editable + tests):
git clone https://github.com/js713-lab/sonic-match-mcp.git
cd sonic-match-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env # optional keys
# stdio (Claude Desktop / Cursor)
sonicmatch-mcp
# streamable HTTP (web editors)
sonicmatch-mcp --http --port 8765
# same clone, uv
uv venv && uv pip install -e ".[dev]"
uv run sonicmatch-mcp
v0.2 works offline-ish with a 20-track seed catalog aimed at Reel editors (cafe, product, talking-head, travel, food, fashion, event). Gemini, Jamendo, and Freesound are optional and degrade with a note in the tool response. Seed rows have no hosted audio on purpose — preview_mix synthesizes a demo bed. For real ads, point SONICMATCH_LIBRARY_PATH / EPIDEMIC_LIBRARY_PATH / ARTLIST_LIBRARY_PATH at JSON you already licensed.
pytest # generates tiny color mp4s with ffmpeg
Not on PyPI yet. Install from git.
Features
- Watches the picture. Gemini video understanding when
GEMINI_API_KEYis set; otherwise local ffmpeg / audio heuristics (optional Whisper, PySceneDetect, librosa). - License on every row. CC / royalty-free / user-owned library. Non-commercial tracks are never auto-recommended. Generated beds stay out of auto recs.
- Editor-shaped output. 12–20s hook in/out, speech ducking, ffmpeg recipe, mix spec for CapCut / Premiere / DaVinci / your agent.
- Agent-native MCP. stdio for Claude Desktop and Cursor; streamable HTTP for web editors. Never ships raw multi-MB video through the payload — you get an
asset_id. - Works without API keys. 20-track seed catalog for Reels. Optional Jamendo, Freesound, and user-owned Artlist / Epidemic JSON.
- Cuts on the beat.
suggest_cutssnaps scene cuts to a BPM grid and returns EDL-ish intro / peak / outro. - Brand lock. Save BPM / mood / no-vocals kits and pass
brand_kit=…intorecommend_bgm. - Series, not one-offs.
analyze_batch(max 20) clusters mood and returns one shared mini-playlist. - Honest about closed graphs. No fake “trending audio,” official IG stickers, or Content-ID-safe stamps. yt-dlp platform ingest is opt-in.
Tools
| Tool | What it does |
|---|---|
status | ffmpeg / keys / seed count / day-1 risk gates |
ingest_video | Local path or HTTPS URL → asset_id (never video bytes). Platform URLs need SONICMATCH_ALLOW_YTDLP=1 |
analyze_video_music | Mood, energy curve, speech, scenes, hook window, BPM, search queries |
recommend_bgm | 3–7 ranked tracks + why + license + hook in/out |
search_music | Free-text / BPM / mood over seed + optional catalogs |
get_track | One track’s metadata, license, attribution, URLs |
preview_mix | Hook trim, loop, optional ducking → preview files + ffmpeg + mix spec |
export_mix_spec | Mix spec + ffmpeg + attribution (no render unless render=true) |
suggest_cuts | Beat grid, snapped scene cuts, EDL, intro / peak / outro |
generate_bed | Demo bed marked source=generated. Requires i_understand_not_commercially_cleared=true |
save_brand_kit | Persist BPM / moods / no-vocals for recommend_bgm(brand_kit=…) |
analyze_batch | Up to 20 clips → mood cluster + shared mini-playlist |
Also ships a prompt template: “Score this video like an IG music sticker.”
Product rules (Instagram-like, not Instagram)
- Prefer instrumental when
speech_coverage > 0.25 - Recommend a hook window, not the whole song
- Show why (
cuts at 0.8s average, 112 BPM, warm gold hour) - Always return license + attribution text
- 3–7 tracks, not 40
- User can override mood / genre / no-lyrics / platform / energy
- Never claim “cleared for Instagram official sticker” unless it actually is
Claude Desktop
claude_desktop_config.json — after a clone + pip install -e .:
{
"mcpServers": {
"sonicmatch": {
"command": "/absolute/path/to/sonic-match-mcp/.venv/bin/sonicmatch-mcp",
"args": [],
"env": {
"GEMINI_API_KEY": "",
"JAMENDO_CLIENT_ID": "",
"FREESOUND_API_KEY": ""
}
}
}
}
After pip install git+https://github.com/js713-lab/sonic-match-mcp.git, command can be sonicmatch-mcp if that binary is on PATH.
Cursor
.cursor/mcp.json (project) or ~/.cursor/mcp.json. From git, no clone:
{
"mcpServers": {
"sonicmatch": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/js713-lab/sonic-match-mcp.git",
"sonicmatch-mcp"
],
"env": {
"GEMINI_API_KEY": "",
"JAMENDO_CLIENT_ID": "",
"FREESOUND_API_KEY": ""
}
}
}
}
From a clone: "command": "uv", "args": ["--directory", "/absolute/path/to/sonic-match-mcp", "run", "sonicmatch-mcp"]. After pip install, "command": "python3", "args": ["-m", "sonicmatch"] works if that interpreter has the package.
Copy-paste configs: examples/claude_desktop.mcp.json, examples/cursor.mcp.json. User-owned Epidemic/Artlist JSON shape: examples/user_library.example.json. Registry metadata: server.json.
HTTP editors can point at http://127.0.0.1:8765/mcp after sonicmatch-mcp --http.
--http has no authentication. Keep it on loopback. The Docker image binds 0.0.0.0 so the container port works — do not publish that port to the internet. See SECURITY.md.
Architecture
flowchart TB
subgraph mcp [MCP Server - FastMCP / Python - stdio + HTTP]
tools[ingest_video / analyze_video_music / recommend_bgm / preview_mix / export_mix_spec / suggest_cuts]
end
tools --> ingest
tools --> brain
tools --> hub
tools --> mixer
ingest[Ingestor<br/>yt-dlp · ffmpeg · ffprobe · URL/file]
brain[Video Brain<br/>Gemini / local VL · librosa · PySceneDetect · Whisper]
hub[Music Hub<br/>seed CC · Jamendo · Freesound · user library · generate]
mixer[Mixer<br/>ffmpeg · ducking · loop/trim · EDL cuts]
hub --> index[Track index<br/>tags + license + embeddings · SQLite · optional LanceDB]
Hard rule: never send raw multi-MB video through the MCP payload. Store locally, pass an asset_id. Loopback, file://, and private IPs are rejected (SSRF).
VideoSonic profile
Analysis returns structured JSON, not a paragraph:
{
"duration_sec": 18.4,
"aspect": "9:16",
"content_type": "lifestyle",
"has_speech": true,
"speech_coverage": 0.62,
"existing_music": false,
"overall_mood": ["warm", "playful"],
"energy_mean": 0.62,
"energy_curve": [{"t": 0, "energy": 0.3}, {"t": 4, "energy": 0.8}],
"pacing": "fast-cut",
"scenes": [{"start": 0, "end": 3.2, "description": "cafe exterior", "energy": 0.4}],
"hook_window": [9.0, 15.0],
"suggested_bpm": [95, 118],
"avoid": ["dark cinematic drone", "aggressive trap", "lyrics-dense"],
"search_queries": ["warm acoustic pop instrumental cafe"],
"platform_hint": "instagram_reel",
"analyzer": "local"
}
- Primary: Gemini video understanding when
GEMINI_API_KEYis set. - Fallback: ffmpeg scene cuts + WAV energy / silence / ZCR heuristics. Optional
faster-whisper,scenedetect,librosaif installed (pip install 'sonicmatch-mcp[local-vl]').
Music hub
Pluggable, license-first. v0 ships:
| Adapter | When | License reality |
|---|---|---|
Seed catalog (data/seed_tracks.json) | always | 20 CC0 / CC-BY Reel beds + a vocal fixture + a CC-BY-NC fixture (NC is never auto-recommended) |
| Jamendo | JAMENDO_CLIENT_ID | CC, check commercial |
| Freesound | FREESOUND_API_KEY | CC, good for beds/loops not songs |
| User library JSON | SONICMATCH_LIBRARY_PATH / EPIDEMIC_LIBRARY_PATH / ARTLIST_LIBRARY_PATH | you already licensed it; we do not scrape paid sites |
| Generate | generate_bed | always source=generated; local sine demo unless you swap a real model |
Ranking (weighted): mood/energy → instrumental if speech → duration/loop → BPM vs cut rate → license fit → tag embedding cosine → user constraints. recommend_bgm drops non-commercial and generated tracks instead of downranking them.
Tracks are indexed in SQLite (~/.cache/sonicmatch-mcp/db/tracks.sqlite) with a 24-d tag embedding. If lancedb is installed (pip install 'sonicmatch-mcp[embeddings]'), vectors are also upserted there.
Seed tracks have no remote audio files on purpose (you should host files you actually have the rights to). preview_mix synthesizes a CC0 demo bed so the mixer still runs offline. generate_bed is a catalog-miss fallback and is not cleared for ads.
Docker
docker build -t sonicmatch-mcp .
# Loopback-only publish. The process inside the container has no HTTP auth.
docker run --rm -p 127.0.0.1:8765:8765 -v sonic-cache:/data/cache sonicmatch-mcp
Roadmap
Catalog > new tools.
- Freesound adapter (loops / beds)
- Tag embeddings in SQLite (+ optional LanceDB extra)
- Epidemic Sound / Artlist as user-owned JSON plugins (no scrape)
- Beat-grid vs scene-cut suggestions (EDL-ish
suggest_cuts) - MCP registry listing (
server.json) - Generate tool, marked
source=generated(local demo; swap a real model at your own legal risk) - Official MCP registry listing via GitHub Release MCPB (see PUBLISH.md)
- Non-commercial licenses excluded from auto
recommend_bgm - 20 seed beds a Reel editor would actually keep, with audio you host
- User-owned Artlist / Epidemic JSON as the default path for ads
- Real CLAP audio embeddings
- PyPI release
Why this can be a good open-source project
Yes if you nail: (1) video-native analysis, (2) license honesty on every row, (3) editor-shaped output (hook in/out, ducking, mix spec), (4) a catalog someone would keep.
No if you only wrap YouTube Music search, or if the first five recs sound like leftover stock beds.
Day-1 risk gates (enforced in code, not slogans):
| Risk | Gate |
|---|---|
| Content ID | Every rec/search/get_track includes content_id_warning. CC/RF is never "Content-ID-safe". content_id_risk is unknown or likely, never cleared. |
| yt-dlp ToS / broken extractors | Platform URL ingest is off unless SONICMATCH_ALLOW_YTDLP=1. Failures map to YTDLP_EXTRACTOR and tell you to pass a local file. |
| Upload size / SSRF | HTTPS-only remote ingest, no file:// / loopback / private IPs, SONICMATCH_MAX_DOWNLOAD_MB (default 200) on files, HTTP, and yt-dlp --max-filesize. |
| “Trending” is a closed Meta graph | Queries for trending/viral/IG audio/TikTok sound return empty + TRENDING_UNAVAILABLE. recommend_bgm always sets trending_available=false. |
| Generation-model commercial terms | generate_bed refuses unless i_understand_not_commercially_cleared=true. Generated tracks are excluded from auto recommend_bgm. |
Use cases
IG Reel / Story · Shopee product clip · YouTube Shorts agent · CapCut/Premiere companion · campus recap · podcast clipper · travel-vlog batch · brand-kit lock (BPM + no vocals) · silent-film / accessibility · multi-agent studio.
License
MIT. Track licenses are independent of the repo license. Security reports: SECURITY.md.
From CodeCrafter.
<!-- maintainer note 2026-09-16T08:47Z --> <!-- maintainer note 2026-09-16T08:47Z -->Related MCP servers

iCloud Drive Docs
Read-only MCP server for listing, searching, downloading, and reading iCloud Drive documents.

io.github.jschoemaker/mcpgo
Manage your Claude Code MCPs by talking to Claude — list, restart, wrap, and more.

ServiceNow MCP Server
ServiceNow Table API, CMDB, and update sets for Claude and Cursor — read-only mode, audit log, OAuth 2.1+PKCE.

AST for TypeScript, supports creating JSON representations of React components

Ignition MCP
MCP server for Inductive Automation Ignition: tags, alarms, history, and Perspective

Hourly ranked news (AI, markets, sports, world): JSON, e-ink pages, Morning Paper PDF; 25 free/day