[ROS2] 実行時ログを含むrosbagをロードするための自作MCP Server
はじめに
ROS2アプリケーションの開発において、実行時ログの解析は重要なデバッグ作業の一つです。しかし、大量のログデータとソースコードを対照して解析するのは時間がかかる作業でもあります。
そこで、LLMを使用してROS2のログ解析を効率化するために、Model Context Protocol Serverを作成しました。
このMCP Server(Rosout MCP Server)は以下二つの改善を想定しています:
- ログ解析作業の効率化: LLMによるログ解析プロセスの自動化・高速化する
- LLM提案精度の向上: LLMがソースコードと実行時ログを同時に参照することで、提案精度を向上させる
機能
Rosout MCP Serverは以下の機能を提供します:
-
rosbagファイルの読み込み:
/rosout
トピックを含むROS2 rosbagファイルをメモリ内データベースにロード - ログの検索: 時間範囲、ノード名、ログレベル、メッセージ内容による絞り込み検索
以下はrosbagをロードし, コードとログを対照して解析をリクエストしている様子です。
セットアップ
Dockerを使用する場合(推奨)
Dockerの場合、ロード対象のrosbagを配置するpathは"--mount"で指定した<LOCAL_BAG_DIR>に限定されます。recordしたrosbagを<LOCAL_BAG_DIR>に移動してください。
mcp.json
に以下を追加(Cursorの場合):
{
"mcpServers": {
"rosout_db_server": {
"command": "docker",
"args": [
"run", "-i", "--rm", "--net=host",
"--mount", "type=bind,src=<LOCAL_BAG_DIR>,dst=<LOCAL_BAG_DIR>,readonly",
"araitaiga/rosout-mcp:latest"
]
}
}
}
uvを使用する場合
uvの場合、MCPサーバー実行環境にros2がインストールされている必要があります。
また、インストールされているrosのpython versionを指定する必要があります。jazzyならpython 3.12、humbleならpython 3.10です。
rosbagを配置するpathに制限はありません。
jazzy
{
"mcpServers": {
"rosout_db_server": {
"command": "uvx",
"args": [
"--python 3.12",
"--from", "git+https://github.com/araitaiga/rosout_mcp",
"rosout-mcp"
]
}
}
}
humble
{
"mcpServers": {
"rosout_db_server": {
"command": "uvx",
"args": [
"--python 3.10",
"--from",
"git+https://github.com/araitaiga/rosout_mcp",
"rosout-mcp"
]
}
}
}
使用例
- ROS2アプリケーションを実行して、rosbagにログを記録:
ros2 bag record /rosout
- 自然言語でログをロード、フィルタリングを実行:
/path/to/your/rosbag ファイルをロードし、ノードAの動作を解析して
利用可能なツール
-
rosbag_load
: rosbagファイルをメモリ内データベースにロード -
db_status
: データベースの統計情報取得 -
node_list
: 全ノード名の一覧取得 -
db_search
: ログの検索・フィルタリング -
db_init
: データベースの初期化
rosbag_load
rosbagファイルをメモリ内データベースにロードします。
パラメータ:
-
bag_path
(str):/rosout
トピックを記録したrosbagのパス
機能:
- ROS2 rosbag2形式のファイルの
/rosout
トピックのログメッセージをSQLiteのメモリ内データベースに変換 - 既存のデータを保持する追記モード(既存データはクリアされない)
- ロード後にログデータベースの状態を自動取得
戻り値:
{
"status": "success",
"message": "Successfully loaded rosbag from <path> to in-memory database",
"database_status": {
"record_count": 1234,
"time_range": {
"min_timestamp": 1234567890000000000,
"max_timestamp": 1234567890999999999
},
"level_range": {
"min_level": 10,
"max_level": 50
},
"unique_nodes": ["node1", "node2"]
}
}
db_status
メモリ内ログデータベースの現在の状態を取得します。
パラメータ: なし
機能:
- 総レコード数の取得
- ログ時間範囲(最古・最新のタイムスタンプ)の取得
- ログレベル範囲(最小・最大レベル)の取得
- ユニークなノード名のリスト取得
戻り値:
{
"status": "success",
"record_count": 1234,
"time_range": {
"min_timestamp": 1234567890000000000,
"max_timestamp": 1234567890999999999
},
"level_range": {
"min_level": 10,
"max_level": 50
},
"unique_nodes": ["node1", "node2", "node3"]
}
node_list
データベース内の全ユニークノード名のリストを取得します。
パラメータ: なし
機能:
- データベース内に存在する全てのユニークなノード名を取得
- ノード数のカウントも併せて提供
戻り値:
{
"status": "success",
"node_count": 5,
"nodes": ["node1", "node2", "node3", "node4", "node5"]
}
db_search
コア機能です。メモリ内データベースのログを多様な条件でフィルタリング・検索します。
ERRORログをフィルター
解析をリクエスト
パラメータ:
-
start_time
(int): 開始時刻フィルタ(ナノ秒)。無視する場合は -1 -
end_time
(int): 終了時刻フィルタ(ナノ秒)。無視する場合は -1 -
node
(str): ノード名による完全一致フィルタ。無視する場合は空文字列 -
min_level
(int): 最小ログレベル。無視する場合は -1 -
max_level
(int): 最大ログレベル。無視する場合は -1 -
message
(str): メッセージ内容のキーワード検索。無視する場合は空文字列
戻り値:
{
"status": "success",
"count": 42,
"data": [
{
"timestamp": 1234567890123456789,
"node": "node_name",
"level": 20,
"message": "Log message content"
}
]
}
db_init
メモリ内データベースを初期化(全ログデータをクリア)します。
パラメータ: なし
機能:
- メモリ内データベースから既存の全てのログレコードを削除
- 新しいセッションを開始する際やデータベースをリセットする際に使用
戻り値:
{
"status": "success",
"message": "In-memory database initialized successfully"
}
まとめ
Rosout MCP Serverにより、ROS2のログ解析作業を効率化できる可能性があります。CursorなどのMCPクライアントを使用している場合、LLMがソースコードとログデータに同時にアクセスできるようになるため、コードの動的な解析や問題特定などのアウトプットの品質が向上すると考えています。
GitHub:
Docker Hub:
Discussion