はじめに
IBM Power 上の VIOS(Virtual I/O Server)を IBM Bob/Claude などの LLM から直接調査できる MCP サーバーを作りました。
ヘルスチェック・アダプターマッピング確認・障害一次切り分けといった定型的な運用作業を、SSH でログインしてコマンドを打つのではなく LLM に自然言語で依頼するだけで済ませられるようにする、運用を簡易にするためのツールとして作成しています。
実機の VIOS へ接続してすべてのツール実行した内容をご紹介します。
動画
Github リポジトリの内容の動画です。
対象読者: IBM Power / VIOS の運用経験がある方、MCP サーバーの実装例に興味がある方
テスト環境
- ターゲット:
p1002v(ホスト名) - ioslevel:
3.1.4.10
目次
なぜ作成したか
MCP サーバーを作る前に、既存のものがないか調べました。IBM Power 周辺には、すでにいくつか MCP サーバーが存在します。
| 既存の MCP サーバー | 対象 | 接続方式 |
|---|---|---|
| IBM/powervs-mcp-server | IBM Power Virtual Server(IBM Cloud のマネージドサービス) | IBM Cloud REST API |
| IBM/ibmi-mcp-server | IBM i | Db2 for i への SQL |
| IBM z/OS 系 MCP サーバー各種 | メインフレーム | 各種 API |
ただし、いずれもオンプレミスの VIOS そのものには触れません。
名前が近い powervs-mcp-server は IBM Cloud 上の Power Virtual Server が対象で、マネージドサービスの API 越しに「VM が正常に動いているか」を見るものです(ツールは fetch_powervs_vm_health など 11 個の読み取り専用 API 呼び出しで構成されています)。「vhost0 の裏に刺さっているのはどの hdisk か」「NPIV の vfchost がなぜ NOT_LOGGED_IN なのか」といった、VIOS 内部の仮想化構成は守備範囲外です。README にも「IBM 公式のサポート対象ではないサンプル実装」と明記されています。
そこで、オンプレ VIOS に SSH で接続し、lsmap や errlog の出力を構造化して返す MCP サーバーを自作しました。
調査範囲(2026年7月時点)
GitHub リポジトリ検索、Glama MCP レジストリ(約 6 万件登録)、mcp.so、IBM 公式 MCP コレクション を確認。aix-mcp / vios-mcp / powervm-mcp / hmc-mcp といったリポジトリ名の使用例も見当たりませんでした。
見落としがあればコメントで教えていただけると助かります。
自分で作成した近い領域の MCP サーバー
実は、VIOS 以外にも AIX / RHEL ppc64le / IBM SVC(SAN Volume Controller)向けに、同じアプローチで MCP サーバーをいくつか作ってきました。
| リポジトリ | 対象 | 言語 | ツールの傾向 |
|---|---|---|---|
| aix-rhel-mcp-server | AIX / RHEL ppc64le | TypeScript | 健康チェック・errpt・snap/perfpmr/nmon/sosreport 収集など約50ツール。execute_aix_command / execute_rhel_command という任意コマンド実行も含む |
| svc-mcp-server | IBM SAN Volume Controller | TypeScript | ステータス確認 + execute_svc_command(任意 SVC CLI 実行) |
| aix-mcp-server-snap | AIX | Python | snap 収集・errpt 構造化・ファイル転送に特化 |
| aix-mcp-server-py-container | AIX | Python(コンテナ化) |
execute_aix_command を含む基本情報取得系ツール |
| vios-mcp-server(本記事) | VIOS | Python | 任意コマンド実行なし。固定コマンド配列+デバイス名検証のみ |
見ての通り、過去に作ったものの多くは execute_*_command という「任意コマンドを渡せる」汎用ツールを持たせていました。自由度は高い一方で、LLM が実機にどんなコマンドを投げるかを事前に完全には制御できません。
VIOS はクライアント LPAR のストレージ・ネットワークを支える基盤パーティションで、誤操作の影響範囲が他の LPAR より大きくなります。そこで今回は方針を変え、任意コマンド実行ツールを一切持たせず、引数はデバイス名などとして検証したうえで固定コマンド配列に変換する設計にしました(詳細は後述の「安全設計」を参照)。
VIOS とは
VIOS(Virtual I/O Server)は IBM Power Systems の AIX ベースの特殊パーティション(LPAR)で、物理 I/O リソースを他の論理パーティションへ仮想化して提供する役割を担います。
IBM Power の仮想化アーキテクチャにおける位置づけ
IBM Power のサーバーは HMC(Hardware Management Console) によって管理され、物理リソースを複数の LPAR(Logical Partition) に分割して利用します。
VIOS はその中でも特殊なパーティションで、他の LPAR(クライアント LPAR)に代わってストレージ・ネットワーク I/O を処理します。
┌────────────────────────────────────────────────┐
│ IBM Power Server │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │LPAR (AIX)│ │LPAR (IBM │ │LPAR (Lin)│ │
│ │ Client │ │ i) │ │ Client │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────▼──────────────▼──────────────▼─────┐ │
│ │ VIOS(Virtual I/O Server) │ │
│ │ vhost / vfchost / SEA / 仮想メディア │ │
│ └────────────────┬───────────────────────┘ │
│ │ │
│ 物理ディスク・FC HBA・物理 NIC │
└────────────────────────────────────────────────┘
VIOS が提供する主要な仮想化機能
| 機能 | 説明 | 関連コンポーネント |
|---|---|---|
| vSCSI | 物理ディスク・LV をクライアント LPAR へ仮想 SCSI として提供 | vhost / vtscsi |
| NPIV | 物理 FC HBA の WWPN をクライアントへ仮想 FC ポートとして提供 | vfchost |
| SEA | 物理 NIC を複数 LPAR で共有する仮想イーサネットアダプター | ent(Shared Ethernet Adapter) |
| 仮想メディア | ISO イメージをクライアントの仮想 CD/DVD として提供 | Virtual Media Repository |
VIOS MCP サーバーとは
MCP(Model Context Protocol)とは
MCP は Anthropic が策定したオープン標準プロトコルで、LLM(大規模言語モデル)が外部ツールやデータソースと安全にやり取りするための仕組みです。
Claude Desktop や VS Code Copilot など MCP 対応クライアントに登録するだけで、LLM が「ツール」として任意のシステムを呼び出せるようになります。


IBM Bob or Claude(LLM)
↕ MCP(JSON-RPC over stdio)
vios-mcp-server(本サーバー)
↕ SSH
VIOS(Virtual I/O Server)
VIOS MCP サーバーの概要
vios-mcp-server は IBM Power の VIOS に SSH 接続し、仮想化構成の調査・障害解析に必要な情報を LLM から取得できる MCP サーバーです。
日々のヘルスチェックや障害一次切り分けを、都度 SSH でログインして lsmap や errlog を叩く代わりに LLM へ依頼するだけで済むようにする、運用簡易化のためのツールという位置づけです。
Python 3.10+ で実装されており、stdio transport で動作します。
できること(提供ツール一覧)
| カテゴリ | ツール | 概要 |
|---|---|---|
| 基本情報 | vios_targets |
設定済みターゲット・安全設定の確認 |
| 基本情報 | vios_health_summary |
ioslevel・uptime・仮想デバイス・メディアの一括取得 |
| マッピング | vios_adapter_map |
SEA / NPIV vfchost / vSCSI vhost の構造化マッピング |
| マッピング | vios_mapping_report |
同上を LPAR 別 Markdown レポートで出力 |
| 障害解析 | vios_fault_scan |
errlog・lsmap・lspath・lsnports を束ねた障害材料収集 |
| 障害解析 | vios_errlog |
errlog をパースし期間・リソース・種別でフィルタ |
| 冗長性 | vios_redundancy_check |
デュアル VIOS のマッピングを比較し片系のみの LPAR を検出 |
| メディア | vios_media_repository |
Virtual Media Repository・仮想光学デバイスの参照 |
| 診断 | vios_part |
part コマンドでパフォーマンスレポートを生成 |
| 診断 | vios_snap |
snap コマンドで診断データ一式を収集 |
安全設計
任意コマンド実行ツールは提供しません。引数はデバイス名として検証し固定コマンド配列に変換します。
vios_part と vios_snap はファイルを生成するため二重保護(confirm=true + 環境変数 VIOS_MUTATIONS_ENABLED=true)が必要です。
GitHub リポジトリ
次のリポジトリで公開しています。
| 項目 | 内容 |
|---|---|
| ライセンス | MIT |
| 実装言語 | Python 3.10+ |
| 依存ライブラリ | 標準ライブラリのみ(外部パッケージ不要) |
| インストール |
pip install -e . → vios-mcp-server コマンドで起動 |
| テスト |
python -m unittest discover -s tests(54件) |
クイックスタート(MCP クライアント設定例)
{
"mcpServers": {
"vios": {
"command": "vios-mcp-server",
"env": {
"VIOS_TARGETS": "[{\"name\":\"vios1\",\"host\":\"vios1.example.com\",\"user\":\"padmin\"}]",
"VIOS_DEFAULT_TARGET": "vios1",
"VIOS_DRY_RUN": "true"
}
}
}
}
初回は VIOS_DRY_RUN=true で設定し、コマンド内容を確認してから本番稼働に切り替えることをお勧めします。
実装ファイル構成
src/vios_mcp_server/
├── mcp.py # MCP JSON-RPC の入口(stdio transport)
├── config.py # ターゲットと環境変数設定
├── runner.py # local / SSH コマンド実行
├── tools.py # MCP ツール定義と VIOS コマンド組み立て
└── parsers.py # lsmap などのパーサーと issue 検出
tests/ # 設定・パーサー・ツール・MCP 応答の単体テスト
ツール一覧と実機テスト結果
| ツール / パラメータ | 結果 | 実機で確認できた内容 |
|---|---|---|
| 基本情報 | ||
vios_targets |
✅ | p1002v 1台・SSH 鍵認証・mutations_enabled=false |
vios_health_summary |
✅ | ioslevel 3.1.4.10 / uptime 69日 / vfchost 52台・vhost 32台・SEA 2台を一括取得。issues 空 |
| アダプターマッピング | ||
vios_adapter_map family=all |
✅ | 60 LPAR — vSCSI 37件・NPIV 52件・SEA 2件。NOT_LOGGED_IN 18件を issues に自動列挙 |
vios_adapter_map family=vscsi |
✅ | Available 16件。クライアント停止中の未接続 21件を区別して構造化 |
vios_adapter_map family=npiv |
✅ | LOGGED_IN 34件 / NOT_LOGGED_IN 18件。fcs0: 46/64 ports、fcs1: 48/64 ports 使用中 |
vios_adapter_map family=sea |
✅ | ent4 (ent0 backing) / ent5 (ent1 backing) — 共に Available |
vios_mapping_report |
✅ | 60 LPAR 全件の Markdown レポートを生成。LPAR 別バッキングディスク一覧・SEA 表・問題一覧付き |
| 障害スキャン | ||
vios_fault_scan scope=quick |
✅ | NPIV 未ログイン 18件を検出。next_steps に HMC プロファイル・lsnports・SAN ゾーニングの確認を提示 |
vios_fault_scan scope=storage |
✅ | lspath 全件 Enabled(バックアップパス含む)。vSCSI マッピング正常。issues 空 |
vios_fault_scan scope=npiv |
✅ | lsnports で fabric=1・tports=64・aports=46/48 を確認。NOT_LOGGED_IN アダプタを列挙 |
vios_fault_scan scope=network |
✅ | SEA 両系 Available。errlog に SEA HA PARTNER LOST → 復旧の履歴あり(2026-07-03) |
| エラーログ | ||
vios_errlog since_hours=24 |
🔧 修正後 ✅ | VIOS の date +format 非互換を発見。引数なし date + parse_vios_date() で修正後に正常動作 |
vios_errlog error_class=H |
✅ | 14件マッチ。sysplanar0 Permanent エラー 2件・SEA フェイルオーバー・物理リンク up/down を構造化 |
| 冗長性 / メディア | ||
vios_redundancy_check |
ℹ️ info | ターゲット 1台のみのため冗長性評価不可(設計どおりの info)。2台構成なら片系のみの LPAR を自動警告 |
vios_media_repository show |
✅ | リポジトリ 10199 MB(空き 1833 MB)。rhel-10.1-ppc64le-dvd (8365 MB, rw) / vopt_20789c84… (1 MB, ro) |
vios_media_repository list_repository |
✅ | lsrep 出力をそのまま返却。Parent Pool: rootvg |
vios_media_repository list_optical_devices |
✅ | vtopt0/vtopt2 にメディアあり。aixtestu/vtopt1 は No Media |
| 単体テスト: 54 / 54 passed — 0 failures, 0 errors |
実機サンプル出力
1. vios_health_summary — VIOS の基本状態を一括取得
ioslevel・sysstat・lsdev -virtual・lsnports・lsrep・lsvopt を 1 回の呼び出しで並列実行し、
まとめて返します。issues が空なら基本的に正常稼働中と判断できます。
{
"summary": {
"hostname": "p1002v",
"ioslevel": "3.1.4.10",
"uptime": "06:02PM up 69 days, 3:33, 0 users, load average: 2.21, 1.90, 1.99"
},
"parsed": {
"optical_devices": [
{ "vtd": "vtopt0", "media": "vopt_20789c848c1d435eac9ab7a8b7fa9974", "size": "1" },
{ "vtd": "vtopt2", "media": "rhel-10.1-ppc64le-dvd", "size": "8365" }
]
},
"issues": []
}
2. vios_adapter_map family=sea — SEA マッピング
lsmap -all -net の出力を構造化します。物理ロケーションコード (bdphysloc) も含まれるため、
ハードウェア障害時の部品特定にそのまま使えます。
{
"families": {
"sea": {
"records": [
{
"svea": "ent2",
"sea": "ent4",
"backing": "ent0",
"bdphysloc": "U78DB.ND0.WZS02B8-P0-C11-T0",
"physloc": "U9105.41B.785CA21-V2-C2-T0",
"status": "Available"
},
{
"svea": "ent3",
"sea": "ent5",
"backing": "ent1",
"bdphysloc": "U78DB.ND0.WZS02B8-P0-C11-T1",
"physloc": "U9105.41B.785CA21-V2-C3-T0",
"status": "Available"
}
],
"status_counts": { "Available": 2 }
}
},
"issues": []
}
3. vios_adapter_map family=vscsi, lpar_id=3 — LPAR 単位でディスク追跡
lpar_id で絞り込むと「この LPAR にどのディスクが刺さっているか」を即座に確認できます。
LUN アドレス・バッキング hdisk・物理ロケーションコードまで構造化されて返ります。
{
"by_lpar": [{
"lpar_id": 3,
"backing_devices": ["hdisk10", "hdisk3"],
"vscsi": [
{
"adapter": "vhost0",
"vtd": "p1003a_nimvg",
"lun": "0x8200000000000000",
"backing": "hdisk10",
"backing_physloc": "U78DB.ND0.WZS02B8-P0-C8-T0-W500507680D76816E-LA000000000000",
"status": "Available"
},
{
"adapter": "vhost0",
"vtd": "p1003a_rootvg",
"lun": "0x8100000000000000",
"backing": "hdisk3",
"backing_physloc": "U78DB.ND0.WZS02B8-P0-C8-T0-W500507680D76816E-L1000000000000",
"status": "Available"
}
]
}]
}
実際のIBM Bob IDE から実行する vios_adapter_map ツールで作成されたレポート(htmlファイル)の出力は以下のような表示です。
4. vios_errlog error_class=H — エラーログを構造化
errlog の生テキストをパースして日時・リソース・種別を JSON に変換します。
type=P(Permanent)のエントリは要対処なので、このフィールドでフィルタするのが実用的です。
{
"matched_entries": 14,
"total_entries": 15,
"entries": [
{
"identifier": "1FE2DD91",
"occurred_at": "2026-07-03 12:55:00",
"type": "I",
"class": "H",
"resource": "ent5",
"description": "BECOME BACKUP"
},
{
"identifier": "B8C78C08",
"occurred_at": "2026-07-03 12:52:00",
"type": "I",
"class": "H",
"resource": "ent4",
"description": "SEA HA PARTNER LOST"
},
{
"identifier": "BFE4C025",
"occurred_at": "2026-05-16 14:30:00",
"type": "P",
"class": "H",
"resource": "sysplanar0",
"description": "UNDETERMINED ERROR"
}
]
}
type: "P"(Permanent)の sysplanar0 UNDETERMINED ERROR が 2 件記録されています。
実際のIBM Bob IDE から実行する vios_errlog ツールの出力は以下のような表示です。
5. vios_media_repository operation=show — 仮想メディアリポジトリ
VIOS 上の Virtual Media Repository に格納された ISO / vopt を一覧します。
lsrep + lsvopt を 1 回の呼び出しで取得できます。
# lsrep — リポジトリ容量
Size(mb) Free(mb) Parent Pool Parent Size Parent Free
10199 1833 rootvg 51136 4672
# 格納イメージ一覧
Name File Size Optical Access
rhel-10.1-ppc64le-dvd 8365 vtopt2 rw
vopt_20789c848c1d435eac9ab7a8b7fa9974 1 vtopt0 ro
# lsvopt — 仮想光学デバイスとマウント状況
vtd media size
aixtestu No Media n/a
vtopt0 vopt_20789c848c1d435eac9ab7a8b7fa9974 1
vtopt1 No Media n/a
vtopt2 rhel-10.1-ppc64le-dvd 8365
テスト中に発見したバグと自動修復
vios_errlog の since_hours フィルタが常にスキップされる問題
今回のテストは IBM Bob(AI エージェント)を使って実機に対してツールを順番に呼び出す形で実施しました。
Bob が since_hours=24 を指定して vios_errlog を呼び出したところ、ツール応答の issues に
以下の警告が含まれていることに自動で気づき、そのままコードの原因調査・修正・テスト実行まで一気に行いました。
{
"issues": [
{
"severity": "warning",
"section": "vios_time",
"message": "Command exited with rc=1. Review stderr/stdout."
},
{
"severity": "info",
"section": "vios_time",
"message": "Could not read the VIOS clock; since_hours is evaluated against this server's local time instead."
}
]
}
原因
VIOS 時刻取得のために date +%m%d%H%M%y を実行していましたが、
VIOS の Korn shell は +format 引数を受け付けず rc=1 を返します。
フォールバック処理でフィルタが無効化されていました。
# VIOS 上での実行結果
$ date +%m%d%H%M%y
Not a valid command: date +%m%d%H%M%y
Bob による自動修復の流れ
Bob はツールの応答から問題を検知した後、以下の手順を自律的に実行しました。
-
src/vios_mcp_server/tools.pyとparsers.pyを読んで原因を特定 - VIOS の
dateコマンドが AIX 標準形式(Wed Jul 1 14:00:26 JST 2026)を返すことを踏まえ、専用パーサーparse_vios_date()をparsers.pyに追加 -
tools.pyのコマンドを["date", "+%m%d%H%M%y"]→["date"]に変更し、呼び出し先を新関数に差し替え - 既存の単体テスト
test_errlog_since_hours_uses_vios_clockが旧フォーマットのモック値を使っていたことも検知し、テストコードも合わせて修正 -
python -m unittest discoverを実行して 54 件全パスを確認
ユーザーの介入はゼロでした。
修正内容
# parsers.py に追加
_VIOS_DATE_RE = re.compile(
r"^\s*\w+\s+(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+(\d{4})\s*$"
)
def parse_vios_date(output: str | None) -> datetime | None:
"""AIX/VIOS の bare `date` 出力をパースする。
例: 'Wed Jul 1 14:00:26 JST 2026'
"""
if not output:
return None
m = _VIOS_DATE_RE.match(output.strip())
if not m:
return None
try:
return datetime.strptime(f"{m.group(1)} {m.group(2)}", "%b %d %H:%M:%S %Y")
except ValueError:
return None
# tools.py の変更
# Before:
commands["vios_time"] = ["date", "+%m%d%H%M%y"]
now = errlog_timestamp(str(sections["vios_time"]["stdout"]).strip())
# After:
commands["vios_time"] = ["date"]
now = parse_vios_date(str(sections["vios_time"]["stdout"]).strip())
まとめ
| 項目 | 結果 |
|---|---|
| ツールテスト | 17 / 17 ✅ |
| 単体テスト | 54 / 54 ✅ |
| NPIV NOT_LOGGED_IN 自動検出 | 18件 ✅ |
| バグ発見・自動修復 | 1件(since_hours フィルタ)— IBM Bob が検知・修正 |
今回のテストは IBM Bob を使って進めました。
Bob が実機ツールを順番に叩き、応答の issues フィールドを読んでバグを自律検知し、
原因調査・コード修正・テスト実行まで一連の作業をノーハンドで完了しました。
MCP サーバーの開発において「LLM 自身が使いながら直す」というワークフローが実用になることを確認できました。
ご参考まで、以上です。
ご参考
筆者が作成した関連リポジトリ
VIOS 以外にも、同じアプローチで AIX / RHEL ppc64le / IBM SVC 向けの MCP サーバーを作成しています。いずれも筆者(cu0001)が作成したものです。
| リポジトリ | 対象 | 言語 |
|---|---|---|
| vios-mcp-server(本記事) | VIOS | Python |
| aix-rhel-mcp-server | AIX / RHEL ppc64le | TypeScript |
| svc-mcp-server | IBM SAN Volume Controller | TypeScript |
| aix-mcp-server-snap | AIX | Python |
| aix-mcp-server-py-container | AIX(コンテナ化) | Python |
比較として参照した外部の MCP サーバー
| リポジトリ | 対象 |
|---|---|
| IBM/powervs-mcp-server | IBM Power Virtual Server(IBM Cloud のマネージドサービス) |
| IBM/ibmi-mcp-server | IBM i |
| IBM/mcp | IBM 公式 MCP コレクション |





