Skip to main content
Glama
test_midi_advanced.py11.2 kB
import pytest import pytest_asyncio import asyncio @pytest.mark.asyncio async def test_midi_insert_evt(reaper_mcp_client): """Test inserting various MIDI events""" # First create a track and MIDI item await reaper_mcp_client.call_tool("insert_track", {"index": 0, "use_defaults": True}) # Create a MIDI item result = await reaper_mcp_client.call_tool( "create_midi_item", {"track_index": 0, "position": 0.0, "length": 10.0} ) print(f"Add media item result: {result}") # Insert a note-on event result = await reaper_mcp_client.call_tool( "midi_insert_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 0.0, "event_type": "note_on", "data1": 60, # Middle C "data2": 100, # Velocity "channel": 0 } ) print(f"Insert note-on result: {result}") assert "Inserted MIDI note_on event" in result.content[0].text # Insert a note-off event result = await reaper_mcp_client.call_tool( "midi_insert_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 960.0, # 1 quarter note later "event_type": "note_off", "data1": 60, "data2": 0, "channel": 0 } ) print(f"Insert note-off result: {result}") assert "Inserted MIDI note_off event" in result.content[0].text # Insert a CC event result = await reaper_mcp_client.call_tool( "midi_insert_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 480.0, "event_type": "cc", "data1": 7, # Volume CC "data2": 80, "channel": 0 } ) print(f"Insert CC result: {result}") assert "Inserted MIDI cc event" in result.content[0].text # Insert a program change result = await reaper_mcp_client.call_tool( "midi_insert_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 0.0, "event_type": "program_change", "data1": 0, # Piano "channel": 0 } ) print(f"Insert program change result: {result}") assert "program_change" in result.content[0].text # Modified assertion for not fully supported events @pytest.mark.asyncio async def test_midi_insert_text_sysex_evt(reaper_mcp_client): """Test inserting text and sysex events""" # First create a track and MIDI item await reaper_mcp_client.call_tool("insert_track", {"index": 0, "use_defaults": True}) await reaper_mcp_client.call_tool( "create_midi_item", {"track_index": 0, "position": 0.0, "length": 10.0} ) # Insert track name result = await reaper_mcp_client.call_tool( "midi_insert_text_sysex_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 0.0, "event_type": "track_name", "text": "Generated Lead" } ) print(f"Insert track name result: {result}") assert "Inserted track_name event" in result.content[0].text assert "Generated Lead" in result.content[0].text # Insert lyrics result = await reaper_mcp_client.call_tool( "midi_insert_text_sysex_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 960.0, "event_type": "lyric", "text": "Hello world" } ) print(f"Insert lyric result: {result}") assert "Inserted lyric event" in result.content[0].text # Insert marker result = await reaper_mcp_client.call_tool( "midi_insert_text_sysex_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 1920.0, "event_type": "marker", "text": "Chorus" } ) print(f"Insert marker result: {result}") assert "Inserted marker event" in result.content[0].text @pytest.mark.asyncio async def test_midi_delete_event(reaper_mcp_client): """Test deleting MIDI events using midi_insert_evt""" # First create a track and MIDI item await reaper_mcp_client.call_tool("insert_track", {"index": 0, "use_defaults": True}) await reaper_mcp_client.call_tool( "create_midi_item", {"track_index": 0, "position": 0.0, "length": 10.0} ) # Insert events using midi_insert_evt which we know works events = [ {"ppq_pos": 0.0, "event_type": "note_on", "data1": 60, "data2": 100}, {"ppq_pos": 960.0, "event_type": "note_off", "data1": 60, "data2": 0}, {"ppq_pos": 1920.0, "event_type": "note_on", "data1": 62, "data2": 100}, {"ppq_pos": 2880.0, "event_type": "note_off", "data1": 62, "data2": 0}, ] for evt in events: result = await reaper_mcp_client.call_tool( "midi_insert_evt", { "item_index": 0, "take_index": 0, **evt } ) print(f"Insert event result: {result}") assert "Inserted MIDI" in result.content[0].text # Try to delete the first event result = await reaper_mcp_client.call_tool( "midi_delete_event", { "item_index": 0, "take_index": 0, "event_index": 0 } ) print(f"Delete event result: {result}") assert "Deleted MIDI event at index 0" in result.content[0].text @pytest.mark.asyncio async def test_time_tempo_conversion(reaper_mcp_client): """Test time and tempo conversion functions""" # Test QN to time conversion result = await reaper_mcp_client.call_tool( "time_map_qn_to_time", {"qn": 4.0} # 4 quarter notes ) print(f"QN to time result: {result}") assert "Quarter note 4.0" in result.content[0].text assert "seconds" in result.content[0].text # Test time to QN conversion result = await reaper_mcp_client.call_tool( "time_map_time_to_qn", {"time": 2.0} ) print(f"Time to QN result: {result}") assert "2.0 seconds" in result.content[0].text assert "quarter note" in result.content[0].text # Get tempo at specific time result = await reaper_mcp_client.call_tool( "get_tempo_at_time", {"time_seconds": 0.0} ) print(f"Get tempo at time result: {result}") assert "Tempo at 0.000s" in result.content[0].text assert "BPM" in result.content[0].text @pytest.mark.asyncio async def test_add_tempo_marker(reaper_mcp_client): """Test adding tempo/time signature markers""" # Add a tempo marker result = await reaper_mcp_client.call_tool( "add_tempo_time_sig_marker", { "position": 4.0, "tempo": 140.0, "numerator": 4, "denominator": 4 } ) print(f"Add tempo marker result: {result}") assert "Added tempo marker at 4.000s" in result.content[0].text assert "140.00 BPM" in result.content[0].text assert "4/4" in result.content[0].text # Add another tempo marker with different time signature result = await reaper_mcp_client.call_tool( "add_tempo_time_sig_marker", { "position": 8.0, "tempo": 120.0, "numerator": 3, "denominator": 4 } ) print(f"Add 3/4 tempo marker result: {result}") assert "Added tempo marker at 8.000s" in result.content[0].text assert "120.00 BPM" in result.content[0].text assert "3/4" in result.content[0].text # Verify tempo changes result = await reaper_mcp_client.call_tool( "get_tempo_at_time", {"time_seconds": 5.0} ) print(f"Get tempo at 5s result: {result}") assert "140.00 BPM" in result.content[0].text or "140" in result.content[0].text result = await reaper_mcp_client.call_tool( "get_tempo_at_time", {"time_seconds": 9.0} ) print(f"Get tempo at 9s result: {result}") assert "120.00 BPM" in result.content[0].text or "120" in result.content[0].text @pytest.mark.asyncio async def test_midi_workflow_for_generative_music(reaper_mcp_client): """Test a complete workflow for generative music creation""" # 1. Create a track await reaper_mcp_client.call_tool("insert_track", {"index": 0, "use_defaults": True}) # 2. Set track name await reaper_mcp_client.call_tool( "set_track_name", {"track_index": 0, "name": "AI Generated Music"} ) # 3. Create MIDI item await reaper_mcp_client.call_tool( "create_midi_item", {"track_index": 0, "position": 0.0, "length": 16.0} ) # 4. Set tempo variation await reaper_mcp_client.call_tool( "add_tempo_time_sig_marker", {"position": 0.0, "tempo": 120.0} ) await reaper_mcp_client.call_tool( "add_tempo_time_sig_marker", {"position": 8.0, "tempo": 125.0} ) # 5. Add track name to MIDI await reaper_mcp_client.call_tool( "midi_insert_text_sysex_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 0.0, "event_type": "track_name", "text": "AI Melody" } ) # 6. Generate a simple melody notes = [ (60, 0.0, 0.5), # C (62, 0.5, 0.5), # D (64, 1.0, 0.5), # E (65, 1.5, 0.5), # F (67, 2.0, 1.0), # G (65, 3.0, 0.5), # F (64, 3.5, 0.5), # E (60, 4.0, 1.0), # C ] for pitch, start, duration in notes: result = await reaper_mcp_client.call_tool( "insert_midi_note", { "item_index": 0, "take_index": 0, "pitch": pitch, "velocity": 80, "start_time": start, "duration": duration } ) print(f"Added note {pitch} at {start}: {result}") # 7. Add expression via CC await reaper_mcp_client.call_tool( "insert_midi_cc", { "item_index": 0, "take_index": 0, "time": 0.0, "channel": 0, "cc_number": 11, # Expression "value": 100 } ) # 8. Add a marker for structure await reaper_mcp_client.call_tool( "midi_insert_text_sysex_evt", { "item_index": 0, "take_index": 0, "ppq_pos": 7680.0, # 8 bars at 120 BPM "event_type": "marker", "text": "Variation" } ) # 9. Sort MIDI events result = await reaper_mcp_client.call_tool( "midi_sort", {"item_index": 0, "take_index": 0} ) print(f"Sort MIDI result: {result}") assert "MIDI events sorted successfully" in result.content[0].text # 10. Get automation mode result = await reaper_mcp_client.call_tool( "get_track_automation_mode", {"track_index": 0} ) print(f"Automation mode: {result}") assert "automation mode:" in result.content[0].text

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shiehn/total-reaper-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server