Skip to main content
Glama

AbletonMCP Enhanced

by itsuzef
audio_effects_test.py12.3 kB
#!/usr/bin/env python3 """ Audio Effects Testing Script for Ableton MCP. This script tests parameter control for various audio effects to ensure the generic device parameter control implementation works across different devices. """ import socket import json import time import sys import math # Connection settings HOST = "localhost" PORT = 9877 def print_divider(title=""): """Print a divider with an optional title.""" print("\n" + "=" * 80) if title: print(f"{title.center(80)}") print("=" * 80) def send_command(command_type, params=None): """Send a command to the MCP server and return the result.""" if params is None: params = {} print(f"Sending command: {command_type}") print(f"Parameters: {json.dumps(params, indent=2)}") try: # Create a socket connection with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: # Connect to the server sock.connect((HOST, PORT)) # Prepare the command command = { "type": command_type, "params": params } # Send the command sock.sendall(json.dumps(command).encode('utf-8')) # Receive the response response = b"" while True: chunk = sock.recv(4096) if not chunk: break response += chunk # Check if we've received a complete JSON response try: json.loads(response.decode('utf-8')) break # If we can parse it, we have a complete response except json.JSONDecodeError: continue # Keep receiving if the JSON is incomplete # Parse and return the response try: result = json.loads(response.decode('utf-8')) print(f"Response: {json.dumps(result, indent=2)}") return result except json.JSONDecodeError: print(f"Error decoding JSON response: {response.decode('utf-8')}") return {"status": "error", "message": "Failed to decode response"} except Exception as e: print(f"Error sending command: {str(e)}") return {"status": "error", "message": str(e)} def setup_test_track(track_name="Audio Effects Test Track"): """Set up a test track and return its index.""" print_divider(f"SETTING UP TEST TRACK: {track_name}") # Create a MIDI track track_result = send_command("create_midi_track") if track_result.get("status") != "success" or "index" not in track_result.get("result", {}): print("❌ Failed to create a MIDI track for testing") return None track_index = track_result["result"]["index"] print(f"✅ Created MIDI track at index {track_index}") # Rename the track for clarity rename_result = send_command("set_track_name", { "track_index": track_index, "name": track_name }) if rename_result.get("status") == "success": print(f"✅ Renamed track to '{track_name}'") return track_index def load_device(track_index, device_uri, device_name): """Load a device onto a track and return its index.""" print_divider(f"LOADING DEVICE: {device_name}") if track_index is None: print("❌ Cannot load device without a valid track") return None # Load the device onto the track device_result = send_command("load_browser_item", { "track_index": track_index, "item_uri": device_uri }) if device_result.get("status") != "success": print(f"❌ Failed to load {device_name}. Error: {device_result.get('message', 'Unknown error')}") return None print(f"✅ Successfully loaded {device_name} onto the track") # Get track info to find the device index track_info = send_command("get_track_info", {"track_index": track_index}) if track_info.get("status") != "success" or "devices" not in track_info.get("result", {}): print("❌ Failed to get track info") return None # Find the device devices = track_info["result"]["devices"] device_index = None for device in devices: if device_name in device.get("name", ""): device_index = device.get("index", 0) break if device_index is None: print(f"❌ Could not find {device_name} device in track") return None print(f"✅ Found {device_name} at device index {device_index}") return device_index def test_device_parameters(track_index, device_index, device_name): """Test getting and setting parameters for a device.""" print_divider(f"TESTING PARAMETERS FOR: {device_name}") if track_index is None or device_index is None: print("❌ Cannot test without track and device indices") return False # Get all parameters for the device params_result = send_command("get_device_parameters", { "track_index": track_index, "device_index": device_index }) if params_result.get("status") != "success" or "parameters" not in params_result.get("result", {}): print(f"❌ Failed to get parameters for {device_name}") return False parameters = params_result["result"]["parameters"] print(f"✅ Successfully retrieved {len(parameters)} parameters for {device_name}") # Test setting a few key parameters test_parameters = [] # Select a few parameters to test based on the device type for param in parameters: param_name = param.get("name", "") # Skip device on/off parameter if param_name == "Device On": continue # Add parameter to test list if it's not quantized or if it has value items if not param.get("is_quantized", False) or "value_items" in param: test_parameters.append(param) # Limit to 5 parameters for brevity if len(test_parameters) >= 5: break print(f"Selected {len(test_parameters)} parameters to test:") for param in test_parameters: print(f" - {param.get('name')}: {param.get('value')} (min: {param.get('min')}, max: {param.get('max')})") # Test setting each parameter all_passed = True for param in test_parameters: param_name = param.get("name") param_min = param.get("min", 0) param_max = param.get("max", 1) # For quantized parameters with value items, test setting to each value item if param.get("is_quantized", False) and "value_items" in param: value_items = param.get("value_items", []) for i, item in enumerate(value_items): print(f"\nTesting {param_name} = {item} (index {i})") result = send_command("set_device_parameter", { "track_index": track_index, "device_index": device_index, "parameter_name": param_name, "value": i }) if result.get("status") != "success": print(f"❌ Failed to set {param_name} to {item}") all_passed = False continue # Verify the value was set correctly actual_value = result["result"]["value"] if abs(actual_value - i) < 0.01: print(f"✅ Set {param_name} to {item} (value: {actual_value})") else: print(f"⚠️ Set {param_name} to {item}, but actual value is {actual_value}") all_passed = False # For continuous parameters, test min, middle, and max values else: test_values = [param_min, (param_min + param_max) / 2, param_max] for value in test_values: print(f"\nTesting {param_name} = {value}") result = send_command("set_device_parameter", { "track_index": track_index, "device_index": device_index, "parameter_name": param_name, "value": value }) if result.get("status") != "success": print(f"❌ Failed to set {param_name} to {value}") all_passed = False continue # Verify the value was set correctly actual_value = result["result"]["value"] if abs(actual_value - value) < 0.01: print(f"✅ Set {param_name} to {value} (actual: {actual_value})") else: print(f"⚠️ Set {param_name} to {value}, but actual value is {actual_value}") all_passed = False return all_passed def test_compressor(track_index): """Test parameter control for the Compressor device.""" device_name = "Compressor" device_uri = "query:AudioFx#Compressor" device_index = load_device(track_index, device_uri, device_name) if device_index is None: return False return test_device_parameters(track_index, device_index, device_name) def test_reverb(track_index): """Test parameter control for the Reverb device.""" device_name = "Reverb" device_uri = "query:AudioFx#Reverb" device_index = load_device(track_index, device_uri, device_name) if device_index is None: return False return test_device_parameters(track_index, device_index, device_name) def test_auto_filter(track_index): """Test parameter control for the Auto Filter device.""" device_name = "Auto Filter" device_uri = "query:AudioFx#Auto%20Filter" device_index = load_device(track_index, device_uri, device_name) if device_index is None: return False return test_device_parameters(track_index, device_index, device_name) def test_delay(track_index): """Test parameter control for the Delay device.""" device_name = "Delay" device_uri = "query:AudioFx#Delay" device_index = load_device(track_index, device_uri, device_name) if device_index is None: return False return test_device_parameters(track_index, device_index, device_name) def main(): """Run all tests.""" print_divider("ABLETON MCP AUDIO EFFECTS PARAMETER CONTROL TEST") # Check if server is running print("\nChecking connection to MCP server...") session_info = send_command("get_session_info") if session_info.get("status") != "success": print("❌ Error: Failed to connect to MCP server") return 1 print("✅ Successfully connected to MCP server") # Run tests for each device type tests = [ ("compressor", lambda: test_compressor(setup_test_track("Compressor Test Track"))), ("reverb", lambda: test_reverb(setup_test_track("Reverb Test Track"))), ("auto_filter", lambda: test_auto_filter(setup_test_track("Auto Filter Test Track"))), ("delay", lambda: test_delay(setup_test_track("Delay Test Track"))) ] results = {} for name, test_func in tests: print(f"\nRunning test for {name}...") try: result = test_func() results[name] = result except Exception as e: print(f"❌ Test failed with exception: {str(e)}") results[name] = False # Print summary print_divider("TEST SUMMARY") all_passed = True for name, result in results.items(): status = "✅ PASSED" if result else "❌ FAILED" print(f"{name}: {status}") if not result: all_passed = False if all_passed: print("\n✅ All tests passed successfully!") else: print("\n⚠️ Some tests failed. See details above.") return 0 if all_passed else 1 if __name__ == "__main__": sys.exit(main())

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/itsuzef/ableton-mcp'

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