Conversation
I've introduced the ability to get and set parameters for your devices in Ableton Live. New Features: - Added `get_device_parameters` to list all controllable parameters for a device. - Added `set_device_parameter` to modify the value of a specific parameter. To implement this, I updated the following files: - `AbletonMCP_Remote_Script/__init__.py`: Added new handlers to interact with the Live API. - `MCP_Server/server.py`: Updated the server to handle the new commands. - `README.md`: Documented the new capabilities. This functionality works for all Ableton devices, including Max for Live devices that expose their parameters to the Live API.
I've enhanced the device control capabilities with this commit. Here's a summary of my changes: 1. You can now use the `set_device_parameter` function to identify parameters by name, not just by index, making it easier to use. 2. I've introduced a new `delete_device` command so you can remove a device from a track. To implement this, I updated the Ableton Remote Script with logic to find parameters by name and to delete devices via the Live API. I also updated the MCP Server to expose the modified `set_device_parameter` function and the new `delete_device` command. Finally, I documented these new features and added examples to the `README.md`.
I've introduced the ability to create and manage audio tracks, which complements the existing MIDI track functionality. You can now create audio tracks in your Ableton Live session and load audio files into their clip slots. I also updated the documentation to reflect these new capabilities, including examples for creating audio tracks and loading audio clips.
I've introduced a comprehensive set of features for managing scenes in Ableton Live, allowing you to have more structured song control. New Features: - `list_scenes`: Get a list of all scenes in the session. - `fire_scene`: Fire a specific scene by its index. - `create_scene`: Create a new scene at a specific index. - `rename_scene`: Rename a scene. I've also updated the `README.md` to document these new capabilities and provide examples for you.
This commit introduces a powerful new feature: the ability to write automation for device parameters within a clip. New Features: - A `write_automation` tool that can create automation curves for any device parameter. It takes a list of time/value points to create the automation. Implementation Details: - The Ableton Remote Script has been updated with a `_write_automation` command handler. This function handles finding the correct clip, device, and parameter, and then uses the Live API to write the automation points to the parameter's envelope. - The MCP Server now exposes the `write_automation` tool, with a detailed docstring explaining how to use it. - The `README.md` has been updated to document this new capability and provide an example.
This commit introduces a new tool, `get_device_details`, to provide detailed information about a specific device on a track. This new feature allows for the retrieval of key properties of a device, such as its `class_name`, which can be used to identify whether a device is a Max for Live device (`MaxDevice`), a VST plugin, or a native Ableton device. Implementation Details: - The Ableton Remote Script has been updated with a `_get_device_details` command handler. - The MCP Server now exposes the `get_device_details` tool. - The `README.md` has been updated to document this new capability.
This commit introduces a new advanced feature: the ability to programmatically modify Max for Live device files (.amxd). New Features: - A `modify_m4l_device_default` tool that can take an input .amxd file, change the default value of a specified parameter, and save the result as a new .amxd file. Implementation Details: - A new `m4l_utils.py` file has been added to encapsulate the logic for reading, decompressing, parsing, modifying, and writing gzipped JSON .amxd files. - The MCP Server now exposes the `modify_m4l_device_default` tool. - The `README.md` has been updated to document this new advanced capability and provide a clear example.
This commit introduces a new helper tool, `find_device_by_name`, to improve the usability of device-related functions. This tool allows finding the index of a device on a specific track by its name, which can then be used in other tools like `get_device_parameters`, `delete_device`, etc. Implementation Details: - The Ableton Remote Script has been updated with a `_find_device_by_name` command handler. - The MCP Server now exposes the `find_device_by_name` tool. - The `README.md` has been updated to document this new tool.
This commit introduces a new tool, `get_clip_info`, to get detailed information about a specific clip in the Ableton Live session. This tool provides more detailed information than what was previously available, including the clip's color, looping status, start/end markers, and time signature. Implementation Details: - The Ableton Remote Script has been updated with a `_get_clip_info` command handler. - The MCP Server now exposes the `get_clip_info` tool. - The `README.md` has been updated to document this new tool.
This commit introduces a new tool, `show_message`, to display a custom message in Ableton Live's status bar. This feature provides a simple way for the AI to give direct feedback to the user within the Ableton Live application. Implementation Details: - The Ableton Remote Script has been updated with a `_show_message` command handler that utilizes the built-in `show_message` method of the Control Surface. - The MCP Server now exposes the `show_message` tool. - The `README.md` has been updated to document this new tool.
This commit introduces a new set of tools for interacting with Ableton Live's Arrangement View. New Features: - `list_locators`: Get a list of all locators (cue points) in the arrangement. - `create_locator`: Create a new locator at a specific time (in beats). - `set_song_position`: Move the playhead to a specific time in the arrangement. Implementation Details: - The Ableton Remote Script has been updated with new command handlers for each of these actions. - The MCP Server now exposes these commands as tools for the AI client. - The `README.md` has been updated to document these new capabilities.
This commit introduces new tools for managing mixer sends in Ableton Live, allowing for more detailed mix control. New Features: - `list_return_tracks`: Get a list of all return tracks in the session. - `set_send_level`: Set the send level for a specific track and send index. Implementation Details: - The Ableton Remote Script has been updated with new command handlers for these mixer-related actions. - The MCP Server now exposes these commands as tools for the AI client. - The `README.md` has been updated to document these new capabilities.
This commit introduces a wide range of new features to the AbletonMCP project, significantly expanding its capabilities. - **Enhanced Browser Navigation**: The `get_browser_tree` tool is now recursive, allowing for deeper exploration of the Ableton Live browser. - **Scene Management**: New tools have been added to list, fire, create, and rename scenes. - **Advanced Device Control**: It is now possible to get and set device parameters by name, delete devices, and find devices by name. - **Automation**: A new `write_automation` tool allows for the creation of automation curves for device parameters. - **Max for Live Integration**: A new `modify_m4l_device_default` tool allows for the modification of `.amxd` files. - **Arrangement View Control**: New tools have been added to list and create locators, and to set the song position. - **Mixer Control**: New tools have been added to list return tracks and set send levels. - **Audio Track Creation**: A new `create_audio_track` tool has been added. - **User Feedback**: A new `show_message` tool allows for displaying messages in the Ableton Live status bar. - **Documentation**: The `README.md` has been updated to reflect all of the new features.
This commit replaces the existing README.md file with a new, more comprehensive version. The new README.md includes: - A full history of the project. - Detailed installation instructions. - A complete command list with explanations. - A breakdown of all the features we have implemented.
This commit replaces the existing README.md file with a new, more comprehensive version. The new README.md includes: - A full history of the project. - Detailed installation instructions. - A complete command list with explanations and examples. - A breakdown of all the features we have implemented.
WalkthroughAdds extensive Ableton Live command routing and thread-safe execution in the Remote Script, introduces many new MCP server endpoints for scenes/locators/tracks/devices/clips/browser/automation, adds a Max for Live utility to modify default parameter values in .amxd files, updates README with restructured command list and onboarding, and changes get_browser_tree signature. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant MCP_Server
participant AbletonConn
participant RemoteScript
participant LiveApp
Client->>MCP_Server: HTTP/Tool call (e.g., create_scene, set_device_parameter)
MCP_Server->>AbletonConn: get_ableton_connection()
MCP_Server->>RemoteScript: send_command(cmd, params)
alt State-changing command
RemoteScript->>RemoteScript: schedule_message(main-thread)
RemoteScript->>LiveApp: Perform operation
LiveApp-->>RemoteScript: Result
RemoteScript-->>MCP_Server: Result via response_queue
else Read-only command
RemoteScript->>LiveApp: Query
LiveApp-->>RemoteScript: Data
RemoteScript-->>MCP_Server: Data
end
MCP_Server-->>Client: JSON/string response
sequenceDiagram
participant User
participant MCP_Server
participant M4LUtils
User->>MCP_Server: modify_m4l_device_default(input, output, name, value)
MCP_Server->>M4LUtils: set_parameter_default_value(...)
M4LUtils->>M4LUtils: Read .amxd (gzip) -> JSON -> modify -> write (gzip)
M4LUtils-->>MCP_Server: True / Error
MCP_Server-->>User: Success message or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
|||||||||||||||||
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (3)
AbletonMCP_Remote_Script/__init__.py (2)
884-886: Typo breaks 'instruments' path resolution in browser navigationThe string literal is missing the leading 'i' (“nstruments”), preventing correct resolution for “instruments/...”. This will cause valid paths to fall back or fail.
Apply this diff:
- if path_parts[0].lower() == "nstruments": + if path_parts[0].lower() == "instruments": current_item = app.browser.instruments
326-334: Undefined_load_instrument_or_effect: add alias or implementationThe branch for
command_type == "load_instrument_or_effect"currently calls a non-existent method. Since the server and README expect this command, you should either implement_load_instrument_or_effector alias it to the existing_load_browser_item.Locations to update:
- AbletonMCP_Remote_Script/init.py (in the same class as
_load_browser_item)Suggested patch—add this immediately after the
_load_browser_itemdefinition:class RemoteScript: def _load_browser_item(self, track_index, item_uri): """Load a browser item onto a track by its URI""" try: … except Exception as e: … + def _load_instrument_or_effect(self, track_index, uri): + """ + Legacy alias for load_instrument_or_effect: + load an instrument, effect, or audio file from the browser. + """ + return self._load_browser_item(track_index, uri)This ensures the existing branch continues working without duplicating logic.
MCP_Server/server.py (1)
112-145: Serialize send/receive over the shared socketGuard the entire request/response with the connection lock to prevent interleaving payloads.
Apply this diff:
- try: - logger.info(f"Sending command: {command_type} with params: {params}") - - # Send the command - self.sock.sendall(json.dumps(command).encode('utf-8')) - logger.info(f"Command sent, waiting for response...") - - # For state-modifying commands, add a small delay to give Ableton time to process - if is_modifying_command: - import time - time.sleep(0.1) # 100ms delay - - # Set timeout based on command type - timeout = 15.0 if is_modifying_command else 10.0 - self.sock.settimeout(timeout) - - # Receive the response - response_data = self.receive_full_response(self.sock) + try: + logger.info(f"Sending command: {command_type} with params: {params}") + with self.lock: + # Send the command + self.sock.sendall(json.dumps(command).encode('utf-8')) + logger.info(f"Command sent, waiting for response...") + + # For state-modifying commands, add a small delay to give Ableton time to process + if is_modifying_command: + import time + time.sleep(0.1) # 100ms delay + + # Set timeout based on command type (receive_full_response will set its own timeout too) + timeout = 15.0 if is_modifying_command else 10.0 + self.sock.settimeout(timeout) + + # Receive the response + response_data = self.receive_full_response(self.sock)
🧹 Nitpick comments (11)
README.md (2)
52-52: Fix Markdown link syntax for uv websiteThe link uses reference-style brackets but doesn’t define a reference. Use standard inline link syntax.
Apply this diff:
-Otherwise, install from [uv's official website][https://docs.astral.sh/uv/getting-started/installation/] +Otherwise, install from [uv's official website](https://docs.astral.sh/uv/getting-started/installation/)
108-116: Step numbering/order is jumbled in “Installing the Ableton Remote Script”The steps jump from 2 → 4 → 3 → 4. Reorder to be strictly increasing to avoid confusion.
Apply this diff to renumber consistently:
-4. Create a folder called 'AbletonMCP' in the Remote Scripts directory and paste the downloaded '__init__.py' file - -3. Launch Ableton Live - -4. Go to Settings/Preferences → Link, Tempo & MIDI +3. Create a folder called 'AbletonMCP' in the Remote Scripts directory and paste the downloaded '__init__.py' file + +4. Launch Ableton Live + +5. Go to Settings/Preferences → Link, Tempo & MIDIAnd update the following two lines accordingly:
-5. In the Control Surface dropdown, select "AbletonMCP" -6. Set Input and Output to "None" +6. In the Control Surface dropdown, select "AbletonMCP" +7. Set Input and Output to "None"MCP_Server/m4l_utils.py (3)
41-43: Flatten nested dict checks when reading parameter_longnameSlight simplification improves readability and avoids a second key lookup.
Apply this diff:
- longname = None - if "saved_attribute_attributes" in box and "valueof" in box["saved_attribute_attributes"]: - longname = box["saved_attribute_attributes"]["valueof"].get("parameter_longname") + saa = box.get("saved_attribute_attributes", {}) + valueof = saa.get("valueof", {}) + longname = valueof.get("parameter_longname")
19-21: Validate input types early (e.g., new_default_value must be numeric)Guardrails here make error messages clearer than failing later during JSON writes.
Apply this diff:
if not os.path.exists(input_filepath): raise FileNotFoundError(f"Input file not found: {input_filepath}") + if not isinstance(new_default_value, (int, float)): + raise TypeError(f"new_default_value must be numeric, got {type(new_default_value).__name__}")
66-68: Preserve original tracebacks when re-raisingUse exception chaining to avoid losing the original stack and cause.
Apply this diff:
- except Exception as e: - # Re-raise exceptions with a more informative message - raise type(e)(f"Failed to modify M4L device: {e}") + except Exception as e: + # Re-raise with context for easier debugging + raise RuntimeError(f"Failed to modify M4L device: {e}") from eAbletonMCP_Remote_Script/__init__.py (2)
593-598: Validate and normalize automation points before writingCurrently, points are passed through without validation. Non-numeric values or missing keys will cause runtime errors deeper in Live’s API. Recommend validation plus optional sorting by time.
Apply this diff:
- automation_points = [] - for point in points: - automation_points.append((point.get("time"), point.get("value"))) + automation_points = [] + for idx, point in enumerate(points): + t = point.get("time") + v = point.get("value") + if t is None or v is None: + raise ValueError("Each automation point must include 'time' and 'value'") + if not isinstance(t, (int, float)) or not isinstance(v, (int, float)): + raise TypeError("Automation point 'time' and 'value' must be numeric") + automation_points.append((float(t), float(v))) + # Optional: ensure chronological order + automation_points.sort(key=lambda tv: tv[0])
1309-1376: Consider enriching get_browser_tree result with totals and path for better UXThe server formatter looks for 'total_folders', 'path', and 'has_more' (with defaults). Adding a folder count and optional path strings would improve the output fidelity.
If desired, compute and include a total count:
result = { "type": category_type, "categories": [], - "available_categories": browser_attrs + "available_categories": browser_attrs, + "total_folders": 0 } @@ - def process_item_recursive(item, current_depth=0): + def process_item_recursive(item, current_depth=0, current_path=None): if not item or current_depth >= max_depth: return None item_info = { "name": item.name if hasattr(item, 'name') else "Unknown", "is_folder": hasattr(item, 'children') and bool(item.children), "is_device": hasattr(item, 'is_device') and item.is_device, "is_loadable": hasattr(item, 'is_loadable') and item.is_loadable, "uri": item.uri if hasattr(item, 'uri') else None, - "children": [] + "children": [], + "path": (current_path + "/" + item.name) if current_path and hasattr(item, 'name') else (item.name if hasattr(item, 'name') else None) } @@ - for child in item.children: - child_info = process_item_recursive(child, current_depth + 1) + for child in item.children: + child_info = process_item_recursive(child, current_depth + 1, item_info["path"]) if child_info: item_info["children"].append(child_info) return item_info @@ - category_tree = process_item_recursive(category_root) + category_tree = process_item_recursive(category_root, 0, category_name) if category_tree: result["categories"].append(category_tree) + # Update total_folders heuristic + def count_folders(node): + n = 1 + for c in node.get("children", []): + n += count_folders(c) + return n + result["total_folders"] += count_folders(category_tree)MCP_Server/server.py (4)
105-111: Update modifying-commands list to reflect new endpoints (or remove the special-casing)This list controls only small sleeps, but keeping it current helps avoid flakiness on heavier ops like scene/device changes.
Apply this diff to include new modifiers:
is_modifying_command = command_type in [ - "create_midi_track", "create_audio_track", "set_track_name", - "create_clip", "add_notes_to_clip", "set_clip_name", - "set_tempo", "fire_clip", "stop_clip", "set_device_parameter", - "start_playback", "stop_playback", "load_instrument_or_effect" + "create_midi_track", "create_audio_track", "set_track_name", + "create_clip", "add_notes_to_clip", "set_clip_name", + "set_tempo", "fire_clip", "stop_clip", "set_device_parameter", + "start_playback", "stop_playback", "load_instrument_or_effect", + "fire_scene", "create_scene", "rename_scene", "write_automation", + "show_message", "create_locator", "set_song_position", "set_send_level", + "delete_device", "load_browser_item" ]Alternatively, consider removing the special-casing entirely and relying on the Remote Script’s main-thread scheduling.
309-314: Avoid assigning unused variables in fire_scene
resultisn’t used. Either remove the assignment or use the returned info to confirm success.Apply this diff:
- result = ableton.send_command("fire_scene", {"scene_index": scene_index}) - return f"Fired scene {scene_index}." + ableton.send_command("fire_scene", {"scene_index": scene_index}) + return f"Fired scene {scene_index}."
648-656: Align load_instrument_or_effect message with Remote Script response shapeThe Remote Script returns keys: loaded, item_name, track_name, uri. It does not return new_devices or devices_after. Simplify messaging to avoid empty joins.
Apply this diff:
- # Check if the instrument was loaded successfully - if result.get("loaded", False): - new_devices = result.get("new_devices", []) - if new_devices: - return f"Loaded instrument with URI '{uri}' on track {track_index}. New devices: {', '.join(new_devices)}" - else: - devices = result.get("devices_after", []) - return f"Loaded instrument with URI '{uri}' on track {track_index}. Devices on track: {', '.join(devices)}" + # Check if the item was loaded successfully + if result.get("loaded", False): + item_name = result.get("item_name", uri) + return f"Loaded '{item_name}' (URI '{uri}') on track {track_index}."
197-216: Connection liveness check via sendall(b'') is unreliableA zero-length send is often a no-op and won’t detect a dead peer. Consider a lightweight ping (e.g., get_session_info) or a socket recv with MSG_PEEK, though the latter isn’t cross-platform-friendly in Python.
I can draft a safe “ping” helper that issues a short, non-modifying command with its own timeout if you’d like.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
AbletonMCP_Remote_Script/__init__.py(10 hunks)MCP_Server/m4l_utils.py(1 hunks)MCP_Server/server.py(7 hunks)README.md(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
AbletonMCP_Remote_Script/__init__.py (1)
MCP_Server/server.py (5)
get_browser_tree(851-913)create_scene(317-331)create_audio_track(491-504)delete_device(830-848)show_message(1039-1052)
MCP_Server/server.py (2)
MCP_Server/m4l_utils.py (1)
set_parameter_default_value(5-68)AbletonMCP_Remote_Script/__init__.py (1)
get_browser_tree(1310-1377)
🪛 Ruff (0.12.2)
MCP_Server/m4l_utils.py
44-47: Use a single if statement instead of nested if statements
(SIM102)
68-68: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
MCP_Server/server.py
310-310: Local variable result is assigned to but never used
Remove assignment to unused variable result
(F841)
🪛 LanguageTool
README.md
[grammar] ~18-~18: There might be a mistake here.
Context: ...elete devices, and find devices by name. - Automation: Write automation curves fo...
(QB_NEW_EN)
[grammar] ~32-~32: There might be a mistake here.
Context: ...ed device control. - Automation writing. - Max for Live integration. - Arrangement ...
(QB_NEW_EN)
[grammar] ~133-~133: There might be a mistake here.
Context: ...ation about the current Ableton session. - Example: "Get the session info." - `se...
(QB_NEW_EN)
[grammar] ~137-~137: There might be a mistake here.
Context: ...k(): Start playing the Ableton session. - **Example**: "Start playback." - stop_pla...
(QB_NEW_EN)
[grammar] ~139-~139: There might be a mistake here.
Context: ...ck()`: Stop playing the Ableton session. - Example: "Stop playback." ### Track C...
(QB_NEW_EN)
[grammar] ~143-~143: There might be a mistake here.
Context: ...iled information about a specific track. - Example: "Get info for track 1." - `cr...
(QB_NEW_EN)
[grammar] ~145-~145: There might be a mistake here.
Context: ...ex: int = -1)`: Create a new MIDI track. - Example: "Create a new MIDI track." - ...
(QB_NEW_EN)
[grammar] ~147-~147: There might be a mistake here.
Context: ...x: int = -1)`: Create a new audio track. - Example: "Create a new audio track." -...
(QB_NEW_EN)
[grammar] ~153-~153: There might be a mistake here.
Context: ...: float = 4.0)`: Create a new MIDI clip. - Example: "Create a 4-bar clip in track...
(QB_NEW_EN)
[grammar] ~161-~161: There might be a mistake here.
Context: ...clip_index: int)`: Start playing a clip. - Example: "Play the clip in track 1, sl...
(QB_NEW_EN)
[grammar] ~163-~163: There might be a mistake here.
Context: ... clip_index: int)`: Stop playing a clip. - Example: "Stop the clip in track 1, sl...
(QB_NEW_EN)
[grammar] ~167-~167: There might be a mistake here.
Context: ...udio file from the browser onto a track. - Example: "Load the 'Operator' synth on...
(QB_NEW_EN)
[grammar] ~183-~183: There might be a mistake here.
Context: ...st of all scenes in the Ableton session. - Example: "List all scenes." - `fire_sc...
(QB_NEW_EN)
[grammar] ~187-~187: There might be a mistake here.
Context: ...eate a new scene in the Ableton session. - Example: "Create a new scene." - `rena...
(QB_NEW_EN)
[grammar] ~193-~193: There might be a mistake here.
Context: ...tree of browser categories from Ableton. - Example: "Get the browser tree for ins...
(QB_NEW_EN)
[grammar] ~197-~197: There might be a mistake here.
Context: ...d then load a specific drum kit into it. - Example: "Load the '808 Core Kit' on t...
(QB_NEW_EN)
[grammar] ~201-~201: There might be a mistake here.
Context: ... modified default value for a parameter. - Example: "Take the device 'MyReverb.am...
(QB_NEW_EN)
[grammar] ~205-~205: There might be a mistake here.
Context: ...ors (cue points) in the Ableton session. - Example: "List all locators." - `creat...
(QB_NEW_EN)
[grammar] ~207-~207: There might be a mistake here.
Context: ...) at a specific time in the arrangement. - Example: "Create a locator at beat 32....
(QB_NEW_EN)
[grammar] ~213-~213: There might be a mistake here.
Context: ...ll return tracks in the Ableton session. - Example: "List all return tracks." - `...
(QB_NEW_EN)
[grammar] ~219-~219: There might be a mistake here.
Context: ...splay a message in Ableton's status bar. - Example: "Show the message 'Hello from...
(QB_NEW_EN)
🔇 Additional comments (2)
README.md (2)
17-24: Command list expansion reads well and matches new API surfaceThe new “Features” bullets align with the new MCP endpoints and Remote Script routing. Clear and consistent phrasing.
130-221: Command List structure is a big improvementThe categorized, signature-style listing with examples is easy to scan and maps to the new MCP endpoints.
| from dataclasses import dataclass | ||
| from contextlib import asynccontextmanager | ||
| from typing import AsyncIterator, Dict, Any, List, Union | ||
| from .m4l_utils import set_parameter_default_value |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make AbletonConnection thread-safe
Multiple tools can be invoked concurrently; without a lock, writes/reads on a shared socket can interleave and corrupt JSON framing. Add a connection-level lock.
Apply this diff:
-from dataclasses import dataclass
+from dataclasses import dataclass, field
+from threading import LockAnd extend the dataclass:
class AbletonConnection:
@@
- sock: socket.socket = None
+ sock: socket.socket = None
+ lock: Lock = field(default_factory=Lock)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| from dataclasses import dataclass | |
| from contextlib import asynccontextmanager | |
| from typing import AsyncIterator, Dict, Any, List, Union | |
| from .m4l_utils import set_parameter_default_value | |
| # Imports at top of MCP_Server/server.py | |
| from dataclasses import dataclass, field | |
| from threading import Lock | |
| from contextlib import asynccontextmanager | |
| from typing import AsyncIterator, Dict, Any, List, Union | |
| from .m4l_utils import set_parameter_default_value | |
| @dataclass | |
| class AbletonConnection: | |
| sock: socket.socket = None | |
| lock: Lock = field(default_factory=Lock) | |
| # ... rest of class ... |
🤖 Prompt for AI Agents
In MCP_Server/server.py around lines 6 to 9, the AbletonConnection must be made
thread-safe by adding a connection-level asyncio lock and using it to serialize
socket reads/writes; import asyncio and dataclasses.field, add a field like
connection_lock: asyncio.Lock = field(default_factory=asyncio.Lock, init=False,
repr=False) to the dataclass, and then wrap all socket send/receive or JSON
framing code paths with "async with self.connection_lock:" so writes/reads
cannot interleave and corrupt framing.
PR Type
Enhancement
Description
Add comprehensive device parameter control with get/set by name or index
Implement full scene management (list, fire, create, rename)
Add automation writing capabilities for device parameters
Introduce Max for Live device modification utilities
Expand session control with locators, return tracks, and send levels
Diagram Walkthrough
File Walkthrough
__init__.py
Core Ableton Live API integration expansionAbletonMCP_Remote_Script/init.py
get_device_parameters,set_device_parameter,delete_device)list_scenes,fire_scene,create_scene,rename_scene)write_automation)m4l_utils.py
Max for Live device modification utilitiesMCP_Server/m4l_utils.py
.amxdfilesserver.py
MCP server tool expansion and integrationMCP_Server/server.py
README.md
Documentation update for expanded featuresREADME.md
Summary by CodeRabbit
New Features
Documentation