🎹

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()の中身は(非公式)ドキュメントが存在し取得することができます。
https://nsuspray.github.io/Live_API_Doc/11.0.0.xml

まとめ

本記事ではAbletonを操作しているAbletonMCP_Remote_Script/init.pyの実装を眺めていきました。
新しくAIが操作できるものを増やすには、self.song()を操作する関数を定義すると良いことがわかりました。

株式会社ZOZO

Discussion