feat: Add get_notes_from_clip to read MIDI notes from clips#54
feat: Add get_notes_from_clip to read MIDI notes from clips#54billy-and-the-oceans wants to merge 2 commits intoahujasid:mainfrom
Conversation
This adds the ability to read existing MIDI notes from clips, which was previously missing from the API. The new function returns: - clip_name: Name of the clip - length: Clip length in beats - note_count: Number of notes - notes: Array of note objects with pitch, start_time, duration, velocity, mute Changes: - AbletonMCP_Remote_Script/__init__.py: Added _get_notes_from_clip method using clip.get_notes_extended() API, and command handler - MCP_Server/server.py: Added @mcp.tool() get_notes_from_clip function - README.md: Updated capabilities and example commands This enables AI assistants to analyze existing clips, visualize patterns, transpose notes, and build on existing musical content. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The newer version of the mcp library changed the parameter name from 'description' to 'instructions' in FastMCP.__init__(). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughA new feature enables retrieval of MIDI notes from existing clips. Changes include a backend handler in the Ableton remote script that extracts notes and converts them to a serializable format, a public MCP server tool that exposes this functionality, and corresponding documentation updates. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant MCP Server
participant Ableton Script
participant Ableton App
Client->>MCP Server: Call get_notes_from_clip(track_index, clip_index)
MCP Server->>Ableton Script: _process_command(get_notes_from_clip, params)
Ableton Script->>Ableton App: Access clip from track
Ableton App-->>Ableton Script: Clip object with notes
Ableton Script->>Ableton Script: Extract & serialize notes (pitch, timing, velocity, mute)
Ableton Script-->>MCP Server: Return JSON with notes + metadata
MCP Server-->>Client: Indented JSON response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
|||||||||||||||||||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
||||||||||||
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
README.md (1)
132-132: Clear documentation of the new capability.The capability description accurately reflects the new functionality. The "(NEW)" marker is helpful for highlighting recent additions.
Minor suggestion: Consider removing the "(NEW)" tag in a future PR once this feature has been in production for a release or two.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
AbletonMCP_Remote_Script/__init__.pyMCP_Server/server.pyREADME.md
🧰 Additional context used
🪛 Ruff (0.14.10)
MCP_Server/server.py
346-346: Unused function argument: ctx
(ARG001)
372-372: Unused function argument: ctx
(ARG001)
390-390: Do not catch blind exception: Exception
(BLE001)
391-391: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
391-391: Use explicit conversion flag
Replace with conversion flag
(RUF010)
392-392: Use explicit conversion flag
Replace with conversion flag
(RUF010)
AbletonMCP_Remote_Script/__init__.py
497-497: Abstract raise to an inner function
(TRY301)
497-497: Avoid specifying long messages outside the exception class
(TRY003)
502-502: Abstract raise to an inner function
(TRY301)
502-502: Create your own exception
(TRY002)
502-502: Avoid specifying long messages outside the exception class
(TRY003)
523-523: Consider moving this statement to an else block
(TRY300)
532-532: Abstract raise to an inner function
(TRY301)
532-532: Avoid specifying long messages outside the exception class
(TRY003)
537-537: Abstract raise to an inner function
(TRY301)
537-537: Avoid specifying long messages outside the exception class
(TRY003)
542-542: Abstract raise to an inner function
(TRY301)
542-542: Create your own exception
(TRY002)
542-542: Avoid specifying long messages outside the exception class
(TRY003)
568-568: Consider moving this statement to an else block
(TRY300)
🔇 Additional comments (7)
MCP_Server/server.py (3)
371-393: LGTM! Clean implementation with consistent error handling.The new
get_notes_from_clipfunction is well-structured and follows the existing patterns in the codebase. The error handling is appropriate, and returning formatted JSON is correct for this use case.Note on static analysis hints: The unused
ctxparameter warning is a false positive—the MCP framework requires this parameter in tool signatures. The broad exception catch and logging patterns are consistent with all other tools in this file.
345-353: Minor formatting changes look good.The parameter reordering and spacing adjustments improve readability without changing behavior.
189-189: No action needed —instructionsparameter is valid in FastMCP 1.3.0+.The
instructionsparameter is documented in the FastMCP SDK as a valid optional parameter (typestr | None) that provides human-readable instructions for how MCP clients should interact with the server. The usage is correct and matches the library's API.AbletonMCP_Remote_Script/__init__.py (3)
228-231: LGTM! Command routing correctly placed.The new command handler is properly placed alongside other read-only commands like "get_track_info", which correctly avoids the main-thread scheduling used for state-modifying commands.
488-527: Whitespace changes improve readability.The blank line additions in
_add_notes_to_clipmake the function more readable without changing behavior.
528-571: Well-implemented with proper error handling and validation.The
_get_notes_from_clipfunction correctly:
- Validates track and clip indices
- Checks for clip existence
- Uses
get_notes_extendedto retrieve notes with the correct pitch range (pitch_span=128 covers all valid MIDI pitches 0-127)- Converts notes to a serializable format
- Returns structured metadata
README.md (1)
147-148: Excellent example commands.These examples effectively demonstrate both simple retrieval and practical workflows. The transpose example shows how users can combine reading notes with other operations.
|
nice |
User description
Summary
This PR adds a new
get_notes_from_clipfunction that allows reading existing MIDI notes from clips in Ableton Live. This was previously missing from the API - we could write notes but not read them.New capability:
get_notes_from_clip(track_index, clip_index)returns JSON with:clip_name: Name of the cliplength: Clip length in beatsnote_count: Number of notesnotes: Array of note objects (pitch, start_time, duration, velocity, mute)Use Cases
Changes
AbletonMCP_Remote_Script/__init__.py: Added_get_notes_from_clip()method usingclip.get_notes_extended()APIMCP_Server/server.py: Added@mcp.tool()decoratedget_notes_from_clip()functionMCP_Server/server.py: Updated FastMCP init to useinstructionsparameter (newer mcp library compatibility)README.md: Updated capabilities list and example commandsTest Plan
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com
PR Type
Enhancement
Description
Add
get_notes_from_clip()function to read MIDI notes from clipsImplement note retrieval using Ableton's
get_notes_extended()APIUpdate FastMCP initialization parameter from
descriptiontoinstructionsExpand README with new capability and usage examples
Diagram Walkthrough
File Walkthrough
__init__.py
Implement note reading from MIDI clipsAbletonMCP_Remote_Script/init.py
get_notes_from_clipin_process_command()_get_notes_from_clip()method using Ableton'sget_notes_extended()APIfrom notes
array
_add_notes_to_clip()methodserver.py
Add MCP tool for reading clip notesMCP_Server/server.py
@mcp.tool()decoratedget_notes_from_clip()functioninstructionsparameter insteadof deprecated
descriptionnote data
add_notes_to_clip()docstringREADME.md
Document new note reading capabilityREADME.md
NEW marker
transposition workflows
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.