<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust</title><link>https://blog.ast.moe/tags/rust/</link><description>Recent posts from 五里霧中</description><generator>Hugo</generator><item><title>CubaseをMCPから操作するサーバーを作った</title><link>https://blog.ast.moe/blog/2026-08-16/</link><pubDate>Sun, 16 Aug 2026 08:05:11 +0900</pubDate><guid>https://blog.ast.moe/blog/2026-08-16/</guid><description>&lt;p&gt;CubaseをMCPから操作できたら面白そうだなと思って、&lt;a href="https://github.com/ieee0824/cubase_mcp"&gt;Cubase MCP&lt;/a&gt;を作りました。&lt;/p&gt;
&lt;p&gt;MCPクライアントから「再生して」「止めて」「今の状態を教えて」と指示すると、Cubaseのトランスポートを操作したり状態を取得したりできます。&lt;/p&gt;
&lt;p&gt;まだCubaseのすべてを操作できるわけではありません。今回はまず、MCPとCubaseをつなぐところまでを小さく作ってみました。&lt;/p&gt;
&lt;h2 id="何を作ったのか"&gt;何を作ったのか&lt;/h2&gt;
&lt;p&gt;実装はRustで書いたIntegration Daemonです。&lt;/p&gt;
&lt;p&gt;MCPサーバーというと、MCPのToolを実装する部分だけを想像しがちですが、今回はその先にCubaseとの通信も必要になります。&lt;/p&gt;
&lt;p&gt;そこで、MCPクライアントからの要求を受け取るデーモンと、Cubaseへ要求を届けるBridgeを分けました。&lt;/p&gt;
&lt;p&gt;現在使えるToolは次の6個です。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MCP Tool&lt;/th&gt;
&lt;th&gt;できること&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.get_status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cubaseとの接続状態と基本的な状態を取得する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.play&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;再生を開始する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;再生または録音を停止する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.record&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;録音を開始する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.get_transport&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;再生状態、録音状態、テンポ、演奏位置を取得する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cubase.get_capabilities&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;接続中のBridgeが対応している機能を取得する&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;録音もToolとして用意していますが、これは本当に録音が始まります。録音先やRecord Enableの状態を確認してから実行する必要があります。&lt;/p&gt;
&lt;h2 id="全体の構成"&gt;全体の構成&lt;/h2&gt;
&lt;p&gt;全体の流れは次のようになっています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
CLIENT[&amp;#34;MCPクライアント&amp;#34;] --&amp;gt;|&amp;#34;stdio / JSON-RPC&amp;#34;| DAEMON[&amp;#34;cubase_mcp&amp;lt;br/&amp;gt;Rust Integration Daemon&amp;#34;]
DAEMON --&amp;gt;|&amp;#34;Bridge Protocol v1&amp;#34;| MIDI[&amp;#34;MIDI / SysEx Bridge&amp;#34;]
MIDI --&amp;gt;|&amp;#34;MIDI Remote API&amp;#34;| REMOTE[&amp;#34;Cubase MIDI Remote script&amp;#34;]
REMOTE --&amp;gt; CUBASE[&amp;#34;Cubase&amp;#34;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;MCPクライアントと&lt;code&gt;cubase_mcp&lt;/code&gt;の間は、改行区切りのJSON-RPCをstdioでやり取りします。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cubase_mcp&lt;/code&gt;の内部ではMCPのTool名を、&lt;code&gt;transport.play&lt;/code&gt;や&lt;code&gt;transport.get&lt;/code&gt;のようなCubase側のメソッドへ変換します。&lt;/p&gt;
&lt;p&gt;その先のBridgeは、Cubaseと通信するための部分です。Bridgeの論理プロトコルはMCPとは別に定義していて、TCP、MIDI、モックのどれを使っても同じ要求と応答を扱えるようにしています。&lt;/p&gt;
&lt;p&gt;実際のCubaseにはMIDI Bridgeを使います。&lt;/p&gt;
&lt;h2 id="cubaseとはmidi-remoteで通信する"&gt;CubaseとはMIDI Remoteで通信する&lt;/h2&gt;
&lt;p&gt;Cubaseの中にはMIDI Remote APIがあります。&lt;/p&gt;
&lt;p&gt;外部のプログラムからCubaseを直接操作するAPIを探すのではなく、Cubase内で動くMIDI Remoteスクリプトを用意して、そこをControl Bridgeにすることにしました。&lt;/p&gt;</description></item></channel></rss>