Ableton MCPのソースコードを眺める AbletonMCP_Remote_Script 編
推薦基盤ブロックの荒木です。
本記事は ZOZO Advent Calendar 2025 シリーズ 8 の 2 日目です。
概要
本記事はAbleton MCPのソースコードを眺める 全体編の続編です。
前回はMCPサーバーの本体であるMCP_Server/server.pyを眺めました。
本記事では、Abletonを操作しているAbletonMCP_Remote_Script/init.pyのソースコードを読んでいきます。
AbletonMCP_Remote_Script/init.py 解説
このファイルは Ableton Live用のリモートスクリプト で、外部のMCPサーバーとソケット通信を介してAbleton Liveを制御するためのものです。
全体構成
クラス構造
-
AbletonMCP(ControlSurface継承): メインのコントロールサーフェスクラス
主要コンポーネント
1. ソケットサーバー (AbletonMCP_Remote_Script/init.py:75-91)
def start_server(self):
# ポート9877でTCPサーバーを起動
# マルチスレッドで複数のクライアント接続を処理
-
localhost:9877でリッスン - 最大5つの同時接続を受け入れ
- デーモンスレッドで非同期に動作
2. コマンド処理システム (AbletonMCP_Remote_Script/init.py:340-639)
JSONベースのコマンド/レスポンス構造で以下をサポート:
読み取り系コマンド:
-
get_session_info: テンポ、拍子、トラック数などのセッション情報 -
get_track_info: 特定トラックの詳細(クリップ、デバイス、ミキサー設定) -
get_browser_*: ブラウザーのカテゴリやアイテムの取得
書き込み系コマンド (メインスレッドで実行):
-
create_midi_track: MIDIトラック作成 -
create_clip/add_notes_to_clip: クリップ作成とMIDIノート追加 -
set_tempo/set_track_name/set_clip_name: 設定変更 -
fire_clip/stop_clip: クリップの再生/停止 -
start_playback/stop_playback: セッション再生制御 -
load_browser_item: ブラウザーアイテムの読み込み
3. スレッド安全性 (AbletonMCP_Remote_Script/init.py:210-338)
# 状態変更コマンドは schedule_message() でメインスレッドに委譲
response_queue = queue.Queue()
self.schedule_message(0, main_thread_task)
- Ableton LiveのAPIはメインスレッドでのみ安全に動作
-
queue.Queue()を使った結果の受け渡し - タイムアウト10秒で処理を保護
4. Python 2/3 互換性
try:
import Queue as queue # Python 2
except ImportError:
import queue # Python 3
- 文字列エンコーディング処理
-
json.dumps()の結果をバイト列として送信(Python 3)またはそのまま送信(Python 2)
5. ブラウザー統合 (AbletonMCP_Remote_Script/init.py:640-1062)
-
_find_browser_item_by_uri(): URI によるアイテム検索(再帰的探索) -
get_browser_tree(): カテゴリツリーの取得 -
get_browser_items_at_path(): パス指定でのアイテム一覧取得
コマンド処理システムの詳細
このファイルの中でも一番主役であるAblentonを操作するコマンド処理システムのコードを読んでいきましょう。
get_seession_info
def _get_session_info(self):
"""Get information about the current session"""
try:
result = {
"tempo": self._song.tempo,
"signature_numerator": self._song.signature_numerator,
"signature_denominator": self._song.signature_denominator,
"track_count": len(self._song.tracks),
"return_track_count": len(self._song.return_tracks),
"master_track": {
"name": "Master",
"volume": self._song.master_track.mixer_device.volume.value,
"panning": self._song.master_track.mixer_device.panning.value
}
}
return result
except Exception as e:
self.log_message("Error getting session info: " + str(e))
raise
現在のセッションの状態を取得するget_session_infoをみてみましょう。
self._songの中身をresultに入れて返しているだけですね。
self._songの作られ方をみてみましょう。
AbletonMCP Class
class AbletonMCP(ControlSurface):
"""AbletonMCP Remote Script for Ableton Live"""
def __init__(self, c_instance):
"""Initialize the control surface"""
...
# Cache the song reference for easier access
self._song = self.song()
AbletonMCP Classで定義されていて、self.song()から代入されています。
self.song()は現在開いているAbletonの情報の参照を返しています。
このメソッドは現在のAbletonの情報と連動しており、このメソッドから現在のAbletonの情報を取得できて、このメソッドに値を代入することでAbletonの情報を更新することができます。
self.song()の中身は(非公式)ドキュメントが存在し取得することができます。
まとめ
本記事ではAbletonを操作しているAbletonMCP_Remote_Script/init.pyの実装を眺めていきました。
新しくAIが操作できるものを増やすには、self.song()を操作する関数を定義すると良いことがわかりました。
Discussion