Skip to main content
Glama
test_dsl_new_tools.py16.9 kB
""" Integration tests for newly added DSL tools These tests verify that the new DSL wrapper functions correctly call REAPER and provide the expected functionality. """ import pytest import logging import re from .test_utils import ( ensure_clean_project, assert_response_contains, assert_response_success, extract_number_from_response ) logger = logging.getLogger(__name__) async def call_dsl_tool(client, tool_name, params): """Helper to call DSL tools and return the text response""" result = await client.call_tool(tool_name, params) return result.content[0].text if result.content else "" @pytest.mark.asyncio class TestDSLTrackManagementNew: """Test new DSL track management tools""" async def test_track_rename(self, reaper_mcp_client): """Test renaming a track""" # Create a track with a unique name unique_name = f"RenameTest_{id(self)}" new_name = f"Renamed_{id(self)}" create_result = await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": unique_name}) print(f"Create result: {create_result}") # Get track list to find the index tracks = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) print(f"Track list: {tracks}") # Rename it by name result = await call_dsl_tool(reaper_mcp_client, "dsl_track_rename", { "track": unique_name, "name": new_name }) assert "Renamed track" in result and f"to '{new_name}'" in result # Verify the name changed tracks_after = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) assert new_name in tracks_after assert unique_name not in tracks_after async def test_track_delete(self, reaper_mcp_client): """Test deleting a track""" # Get initial track count tracks_before = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) initial_count = int(re.search(r'(\d+) tracks?', tracks_before).group(1)) # Create two tracks with unique names delete_name = f"DeleteTest_{id(self)}" keep_name = f"KeepTest_{id(self)}" await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": delete_name}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": keep_name}) # Verify we added 2 tracks tracks_mid = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) mid_count = int(re.search(r'(\d+) tracks?', tracks_mid).group(1)) assert mid_count == initial_count + 2 # Delete one track result = await call_dsl_tool(reaper_mcp_client, "dsl_track_delete", { "track": delete_name }) assert "Deleted track" in result # Verify we're back to initial + 1 tracks_after = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) final_count = int(re.search(r'(\d+) tracks?', tracks_after).group(1)) assert final_count == initial_count + 1 assert keep_name in tracks_after assert delete_name not in tracks_after async def test_track_arm(self, reaper_mcp_client): """Test arming/unarming tracks for recording""" # Create a track await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Recording Track"}) # Arm it result = await call_dsl_tool(reaper_mcp_client, "dsl_track_arm", { "track": "Recording Track", "armed": True }) assert "Track 1 armed for recording" in result # Unarm it result = await call_dsl_tool(reaper_mcp_client, "dsl_track_arm", { "track": "Recording Track", "armed": False }) assert "Track 1 unarmed for recording" in result async def test_track_duplicate(self, reaper_mcp_client): """Test duplicating a track""" # Create a track with specific settings await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Original Track"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_volume", { "track": "Original Track", "volume": "-6dB" }) # Duplicate it result = await call_dsl_tool(reaper_mcp_client, "dsl_track_duplicate", { "track": "Original Track" }) assert "Duplicated track 1" in result # Verify we now have 2 tracks tracks = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) assert "2 tracks" in tracks async def test_track_color(self, reaper_mcp_client): """Test coloring tracks""" # Create a track await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Colorful Track"}) # Color it red result = await call_dsl_tool(reaper_mcp_client, "dsl_track_color", { "track": "Colorful Track", "color": "red" }) assert "Colored track 1 red" in result # Try other colors for color in ["blue", "green", "yellow", "purple"]: result = await call_dsl_tool(reaper_mcp_client, "dsl_track_color", { "track": 0, # Use index "color": color }) assert f"Colored track 1 {color}" in result @pytest.mark.asyncio class TestDSLNavigationAndTransport: """Test new DSL navigation and transport tools""" async def test_go_to_positions(self, reaper_mcp_client): """Test navigating to different positions""" # Go to beginning result = await call_dsl_tool(reaper_mcp_client, "dsl_go_to", { "position": "start" }) assert "Moved to 0.0 seconds" in result # Go to specific time result = await call_dsl_tool(reaper_mcp_client, "dsl_go_to", { "position": 10.5 }) assert "Moved to 10.5 seconds" in result # Go to end result = await call_dsl_tool(reaper_mcp_client, "dsl_go_to", { "position": "end" }) assert "Moved to" in result and "seconds" in result async def test_record(self, reaper_mcp_client): """Test starting recording""" # Create and arm a track first await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Record Track"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_arm", { "track": "Record Track", "armed": True }) # Start recording result = await call_dsl_tool(reaper_mcp_client, "dsl_record", {}) assert "Recording started" in result # Stop recording await call_dsl_tool(reaper_mcp_client, "dsl_stop", {}) @pytest.mark.asyncio class TestDSLEditOperations: """Test new DSL editing operations""" async def test_undo(self, reaper_mcp_client): """Test undo functionality""" # Do something to undo await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Track to Undo"}) # Undo it result = await call_dsl_tool(reaper_mcp_client, "dsl_undo", {}) assert "Undid last action" in result # Verify track is gone tracks = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) assert "Track to Undo" not in tracks or "0 tracks" in tracks async def test_split_items(self, reaper_mcp_client): """Test splitting items at cursor""" # Create a track with an item await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Split Test"}) await call_dsl_tool(reaper_mcp_client, "dsl_loop_create", { "track": "Split Test", "time": "4 bars", "midi": True }) # Move cursor to middle await call_dsl_tool(reaper_mcp_client, "dsl_go_to", {"position": 2.0}) # Split at cursor result = await call_dsl_tool(reaper_mcp_client, "dsl_split", { "position": "cursor" }) assert "Split" in result or "No items selected" in result async def test_fade_operations(self, reaper_mcp_client): """Test fade in/out operations""" # Create track with audio item await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Fade Test"}) # Note: Need selected items for fades to work # This will likely fail without items, but shows the API # Fade in result = await call_dsl_tool(reaper_mcp_client, "dsl_fade", { "type": "in", "duration": 0.5 }) assert "fade in" in result.lower() or "no" in result.lower() # Fade out result = await call_dsl_tool(reaper_mcp_client, "dsl_fade", { "type": "out", "duration": 0.5 }) assert "fade out" in result.lower() or "no" in result.lower() async def test_normalize(self, reaper_mcp_client): """Test normalizing items""" # This requires selected items result = await call_dsl_tool(reaper_mcp_client, "dsl_normalize", { "target": "selected" }) assert "Normalized" in result or "No items" in result.lower() async def test_reverse(self, reaper_mcp_client): """Test reversing audio""" # This requires selected audio items result = await call_dsl_tool(reaper_mcp_client, "dsl_reverse", { "target": "selected" }) assert "Reversed" in result or "No items" in result.lower() @pytest.mark.asyncio class TestDSLProjectOperations: """Test new DSL project operations""" async def test_save_project(self, reaper_mcp_client): """Test saving project""" # Create some content await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Save Test Track"}) # Save project result = await call_dsl_tool(reaper_mcp_client, "dsl_save", {}) assert "Project saved" in result # Save as (note: implementation may be limited) result = await call_dsl_tool(reaper_mcp_client, "dsl_save", { "name": "Test Project" }) assert "save" in result.lower() async def test_render_project(self, reaper_mcp_client): """Test rendering/bouncing project""" # Create content to render await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Render Track"}) # Render as wav result = await call_dsl_tool(reaper_mcp_client, "dsl_render", { "format": "wav", "what": "project" }) assert "Rendered project as wav" in result @pytest.mark.asyncio class TestDSLMarkersAndRegions: """Test new DSL marker and region tools""" async def test_add_marker(self, reaper_mcp_client): """Test adding markers""" # Add marker at current position result = await call_dsl_tool(reaper_mcp_client, "dsl_marker", { "action": "add", "name": "Verse Start" }) assert "Added marker 'Verse Start'" in result # Add marker at specific position result = await call_dsl_tool(reaper_mcp_client, "dsl_marker", { "action": "add", "name": "Chorus", "position": 30.0 }) assert "Added marker 'Chorus' at 30.0 seconds" in result async def test_create_region(self, reaper_mcp_client): """Test creating regions""" # Select a time range first await call_dsl_tool(reaper_mcp_client, "dsl_time_select", {"time": "8 bars"}) # Create region from selection result = await call_dsl_tool(reaper_mcp_client, "dsl_region", { "action": "create", "name": "Intro" }) assert "Created region 'Intro'" in result # Create region with specific bounds result = await call_dsl_tool(reaper_mcp_client, "dsl_region", { "action": "create", "name": "Verse", "start": 10.0, "end": 30.0 }) assert "Created region 'Verse' from 10.0 to 30.0 seconds" in result @pytest.mark.asyncio class TestDSLSelectionOperations: """Test new DSL selection tools""" async def test_select_all_none(self, reaper_mcp_client): """Test selecting all or no items""" # Create track with items await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Selection Test"}) await call_dsl_tool(reaper_mcp_client, "dsl_loop_create", { "track": "Selection Test", "time": "4 bars", "midi": True }) # Select all result = await call_dsl_tool(reaper_mcp_client, "dsl_select", { "what": "all" }) assert "Selected all items" in result # Select none result = await call_dsl_tool(reaper_mcp_client, "dsl_select", { "what": "none" }) assert "Deselected all items" in result @pytest.mark.asyncio class TestDSLOrganizationTools: """Test new DSL organization tools""" async def test_group_tracks(self, reaper_mcp_client): """Test grouping tracks into folders""" # Create multiple tracks await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Drum Kick"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Drum Snare"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Drum Hi-Hat"}) # Group them result = await call_dsl_tool(reaper_mcp_client, "dsl_group_tracks", { "name": "Drums" }) assert "Grouped tracks into folder" in result @pytest.mark.asyncio class TestDSLRoutingTools: """Test new DSL routing tools""" async def test_create_send(self, reaper_mcp_client): """Test creating sends between tracks""" # Create source and destination tracks await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Vocals"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Reverb Bus"}) # Create send result = await call_dsl_tool(reaper_mcp_client, "dsl_send", { "from_track": "Vocals", "to_track": "Reverb Bus", "amount": -6.0 }) assert "Created send from track 1 to track 2" in result @pytest.mark.asyncio class TestDSLCompleteWorkflow: """Test a complete workflow with new tools""" async def test_complete_mixing_workflow(self, reaper_mcp_client): """Test a complete mixing workflow using new DSL tools""" # Create and organize tracks await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Lead Vocal"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Backing Vocal 1"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Backing Vocal 2"}) await call_dsl_tool(reaper_mcp_client, "dsl_track_create", {"name": "Reverb Return"}) # Color code tracks await call_dsl_tool(reaper_mcp_client, "dsl_track_color", { "track": "Lead Vocal", "color": "red" }) await call_dsl_tool(reaper_mcp_client, "dsl_track_color", { "track": "Reverb Return", "color": "blue" }) # Set up sends for track in ["Lead Vocal", "Backing Vocal 1", "Backing Vocal 2"]: await call_dsl_tool(reaper_mcp_client, "dsl_send", { "from_track": track, "to_track": "Reverb Return", "amount": -12.0 }) # Add markers for song structure await call_dsl_tool(reaper_mcp_client, "dsl_marker", { "action": "add", "name": "Intro", "position": 0.0 }) await call_dsl_tool(reaper_mcp_client, "dsl_marker", { "action": "add", "name": "Verse 1", "position": 10.0 }) # Create regions await call_dsl_tool(reaper_mcp_client, "dsl_region", { "action": "create", "name": "Chorus", "start": 30.0, "end": 50.0 }) # Save the project result = await call_dsl_tool(reaper_mcp_client, "dsl_save", {}) assert "Project saved" in result # Verify the structure tracks = await call_dsl_tool(reaper_mcp_client, "dsl_list_tracks", {}) assert "4 tracks" in tracks

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