Skip to main content
Glama

svs-mcp

An MCP (Model Context Protocol) server for Synthesizer V Studio 2 Pro, focused on AI-driven input of lyrics and notes: compose melodies, flow lyrics onto them, and fine-tune pronunciation — all from an AI client such as Claude.

  • macOS + SV Studio 2 Pro only. Local build only (not published to npm).

  • Design notes and background live in docs/plan.md.

How it works

SV's scripting API has no network access, so a small Lua script runs inside SV Studio and exchanges JSON files with the MCP server:

AI client (Claude, etc.)
   │ MCP (stdio)
   ▼
svs-mcp server (Node.js)
   │ request.json / response.json in ~/.svs-mcp/bridge/
   ▼
SVSMCPBridge.lua (resident script inside SV Studio, polls every 100ms)

Requests carry unique IDs (stale responses are discarded) and all file writes are atomic (temp file + rename).

Related MCP server: Suno Autopilot MCP

Setup

Requirements: Node.js 20+, Synthesizer V Studio 2 Pro on macOS.

npm install
npm run build
npm run install-sv   # copies the bridge scripts into SV's scripts folder

Then, in SV Studio:

  1. Run Scripts > Rescan (or restart SV Studio).

  2. Run Scripts > SVS MCP > "SVS MCP Bridge: Start". A dialog confirms the bridge is running; it keeps running in the background.

Finally, register the server with your MCP client:

{
  "mcpServers": {
    "svs-mcp": {
      "command": "node",
      "args": ["/path/to/svs-mcp/dist/index.js"]
    }
  }
}

To verify the setup without an MCP client, run npm run ping — it prints SV's host info when the bridge answers, or setup guidance when it doesn't (exit 1), which also makes the whole setup scriptable for an AI agent: only the two Scripts-menu clicks above need a human.

To stop the bridge, run "SVS MCP Bridge: Stop" from the Scripts menu. To remove everything, npm run uninstall-sv.

Tools

Tool

Purpose

ping

Check the bridge is alive; returns SV host info

get_project_info

Project overview: tempo, time signatures, tracks, groups, mixer state

get_notes

List notes (lyrics, pitch, position) of a track/group, filterable by measure

add_track

Add a track

create_group

Add a note group to a track

insert_notes

Insert notes: lyrics + pitch ("C4") + musical position (measure/beat) + note value ("1/8")

update_notes

Edit lyrics/pitch/timing of existing notes by index

delete_notes

Delete notes by index

set_lyrics

Flow lyrics (one syllable per note) onto an existing melody

get_phrases

Analyze a melody into phrases/sections with repetition (shape) labels

set_time_signature

Add/update/remove time signature marks (align SV's grid with the music)

open_lyrics_editor

Browser page for the user to adjust syllable boundaries before applying

get_lyrics_editor_result

Fetch the user-edited syllable plan from the editor

get_phonemes

Inspect the phonemes SV will actually sing

set_phonemes

Override phonemes per note ("k a"); empty string resets

set_language

Per-note language override for mixed-language lyrics

get_note_attributes

Read per-note voice attributes (per-phoneme strength/timing, vibrato, …)

set_note_attributes

Write them — e.g. copy a hand-tuned note to the other repeats of a phrase

flatten_pitch

Flatten residual vibrato on given notes with a pen-tool pitch curve shaped like a hand-drawn one

get_pitch_controls

List pen-tool pitch curves / anchor points (optionally with points)

add_pitch_curves / delete_pitch_controls

Write raw pitch curves (e.g. copy a hand-drawn one) / delete them

Positions and durations use musical notation (1-based measures/beats, note values like 1/8 or dotted 1/8.); the server converts to SV's internal blicks. Japanese lyrics take one kana per note; - extends the previous vowel.

For putting lyrics on an imported MIDI melody, see docs/lyrics-workflow.md.

Important: groups and singers

In SV Studio 2 the singer is attached per note group, and notes placed in a track's main group are not synthesized (they appear in the piano roll but stay silent). Therefore:

  • insert_notes targets the first non-main group by default and auto-creates a group when the track has none.

  • New tracks/groups inherit SV's default singer. There is no scripting API for singer selection, so if a group has no singer, pick one in the SV UI (select a note of the group, then use the Voice panel).

Troubleshooting

  • Tool calls time out — the bridge is probably not running. Run "SVS MCP Bridge: Start" in SV Studio. Only one MCP server instance should talk to one SV instance.

  • Notes appear but don't sound — check that the notes are in a non-main group (get_project_info shows the groups) and that the group has a singer assigned in the Voice panel. Also check track/group mute states, which get_project_info reports.

  • Wrong pronunciation — inspect with get_phonemes, then correct with set_phonemes or set_language.

Development

npm test        # unit + protocol tests + e2e against the real Lua bridge (needs `lua` on PATH)
npm run build   # tsc

test/sv-stub.lua emulates the SV host so the actual bridge script can be tested without SV Studio. After changing sv-scripts/, re-run npm run install-sv and restart the bridge from SV's Scripts menu.

License

MIT. Bundles rxi/json.lua (MIT) inside the bridge script.

Available Tools

16 tools
add_trackA

Add a new track to the current Synthesizer V Studio project and return its 1-based track index. New tracks and groups inherit SV's default singer; if no singer is configured, the user must pick one in the SV UI.

Inputs: name.

create_groupA

Create a new empty note group on a track and return its group index. In SV Studio 2 the singer is assigned per group, so this is the usual first step before insert_notes when no suitable group exists yet (insert_notes also auto-creates a group when the track has none). The group inherits SV's default singer.

Inputs: track (required), name.

delete_notesA

Delete notes by their current onset-order indices (from get_notes). Remaining notes are renumbered afterwards, so re-read with get_notes before further edits. One undo step.

Inputs: track (required), indexes (required), group.

get_lyrics_editor_resultA

Fetch the syllable plan the user submitted from the lyrics editor page (see open_lyrics_editor). Returns submitted=false when nothing has been submitted yet — ask the user to press the submit button.

Inputs: no named parameters.

get_notesA

List the notes of a track in the current Synthesizer V Studio project. Track indices are 1-based (see get_project_info). Note indices are ordered by onset and SHIFT whenever notes are inserted, deleted or moved, so always re-read before editing. Positions are formatted as measure.beat (both 1-based); phonemes is only present when a user override is set on the note.

Inputs: track (required), group, toMeasure, fromMeasure.

get_phonemesA

Get the phonemes actually used for synthesis for every note in a group (SV's text-to-phoneme output), alongside any user overrides. Useful to check pronunciation before or after edits. If complete is false the converter was still running — retry after a moment.

Inputs: track (required), group.

get_phrasesA

Analyze a track's melody into phrases by finding rests between notes — the recommended first step when flowing lyrics onto an imported melody. Each phrase reports its note index range, note count (= syllables needed), position, pitch range, current lyrics, and a shape label — phrases sharing a letter have an identical melody, which usually means they carry the same (or parallel) lyric line. Long rests are flagged as likely section boundaries. Then assign lyrics phrase by phrase with set_lyrics using each phrase's firstNote index.

Inputs: track (required), group, restThreshold, sectionThreshold.

get_project_infoA

Get an overview of the project currently open in Synthesizer V Studio: file name, tempo marks, time signatures, and the track list with note counts. Track indices returned here are used by all other tools.

Inputs: no named parameters.

insert_notesA

Insert notes into a track (1-based index) of the current Synthesizer V Studio project. Each note needs lyrics, pitch, duration, and a start position; when start is omitted the note begins right after the previous note in this call (the first note must have an explicit start). The insertion is one undo step. Lyric conventions: Japanese lyrics use ONE kana (or small-kana cluster like きゃ) per note; use "-" as the lyric to extend the previous vowel across a note; use "+" to continue a multi-syllable English word. Returns a snapshot of all notes overlapping the inserted range, with fresh indices.

Inputs: notes (required), track (required), group.

open_lyrics_editorA

Open a local browser page where the user can review and adjust the proposed lyric syllable boundaries BEFORE they are applied (per the lyric workflow, readings must be confirmed first). Each phrase is one editable line of space-separated syllables (e.g. fixing あし た to あ した) with a live count against the phrase's note count. After the user says they submitted, call get_lyrics_editor_result and apply the edited plan with set_lyrics.

Inputs: phrases (required), title.

pingA

Check that the bridge script inside Synthesizer V Studio is running. Returns host information (SV edition, version, OS) on success. Call this first if other tools time out.

Inputs: no named parameters.

set_languageA

Set a per-note language override for mixed-language songs (e.g. an English word inside Japanese lyrics). Applies to the given note indices. Pass an empty string to reset notes to the group/track default language.

Inputs: track (required), indexes (required), language (required), group.

set_lyricsA

Assign lyrics to consecutive existing notes, starting at a note index (from get_notes) — the typical way to put lyrics on an existing melody. Each array element goes to one note, in onset order. Japanese: ONE kana (or small-kana cluster like きゃ) per note; "-" extends the previous vowel; "+" continues a multi-syllable English word. Fails if the array runs past the last note. One undo step.

Inputs: track (required), lyrics (required), startIndex (required), group.

set_phonemesA

Override the phonemes of specific notes (by onset-order index from get_notes). Phonemes are space-separated, e.g. Japanese "k a", English "hh ah l ow" (romaji-style for Japanese, ARPABET-style for English). Pass an empty string to remove the override and return to the automatic pronunciation. One undo step.

Inputs: notes (required), track (required), group.

set_time_signatureA

Add, update or remove time signature marks so SV's grid matches the music (useful after importing MIDI without meter information; see get_phrases for inferring the real meter from the notes). Removals are applied before additions. NOTE: this changes how measure/beat positions map to time for every other tool, so set signatures before doing position-based work. One undo step. Returns the resulting signature list.

Inputs: marks, remove.

update_notesA

Edit existing notes by their current onset-order index (from get_notes). Only the provided fields change. Moving a note in time can re-sort the group, so use the returned snapshot (fresh indices) for any follow-up edits instead of the old indices. One undo step.

Inputs: notes (required), track (required), group.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 16 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, with only minor overlap between update_notes and set_lyrics for lyric changes. The two lyrics-editor tools are a complementary pair, and note CRUD is cleanly separated into insert/update/delete.

    Naming Consistency4/5

    Tool names are mostly verb_noun in snake_case, but 'ping' stands alone and the set mixes 'add', 'create', and 'insert' for similar actions. Still predictable and readable overall.

    Tool Count4/5

    At 16 tools, this is slightly above the typical well-scoped range, but the complexity of controlling Synthesizer V justifies the number. Each tool serves a distinct purpose and there is no evident redundancy.

    Completeness3/5

    The tool set provides solid coverage for notes (CRUD), lyrics, phonemes, and phrase analysis, but lacks delete operations for tracks and groups, and offers no API to set the singer. These are notable gaps in lifecycle management that could force UI workarounds.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers