# プラグイン: MQTTでのコマンドとレスポンス

**想定読者:** MQTTでコマンドを受け取り、レスポンスをパブリッシュするプラグインを実装する統合担当者。ブリッジ、プロキシ、アクション振り分けなど、リクエスト駆動の双方向パターン向けです。

最小構成のプラグイン例は主に外向きのパブリッシュのみを扱います。本例では内向きを追加し、プラグインが `Commands/+` トピックをサブスクライブして各コマンドを処理し、対応する `Responses/+` トピックへ結果をパブリッシュします。別の `Status` トピックでヘルス信号を送ります。同一のJSONでWindows、Linux、macOSをカバーするクロスプラットフォーム例です。

まだ[プラグイン: 最小構成 (Windows)](/keeperpam/jp/endpoint-privilege-manager/integrations/examples/plugin-minimal-windows.md) を読んでいない場合は、先にそちらをご覧ください。本ページはコマンド／レスポンスのトピック配置に焦点を当て、Windows版で述べた各フィールドの説明は繰り返しません。

## プラグインのJSON <a href="#the-plugin-json" id="the-plugin-json"></a>

```json
{
  "id": "MyWorker",
  "name": "My Worker",
  "description": "Receives commands and publishes responses over MQTT.",
  "version": "1.0.0",

  "pluginType": "Executable",
  "executablePath": "bin/MyWorker/MyWorker.exe",
  "supportedPlatforms": ["Windows", "Linux", "macOS"],

  "Subscription": {
    "Topic": "MyWorker",
    "Qos": 2,
    "CleanSession": true
  },

  "metadata": {
    "mqttRole": ["subscriber", "publisher"],
    "mqttTopics": {
      "publish": [
        "KeeperLogger",
        "MyWorker/Responses/+",
        "MyWorker/Status"
      ],
      "subscribe": [
        "MyWorker/Commands/+"
      ]
    }
  },

  "startupPriority": 50,
  "autoStart": true,
  "executionContext": "Service",
  "requiresMonitoring": true,
  "autoRestart": true
}
```

## 変更する箇所 <a href="#what-to-change" id="what-to-change"></a>

<table><thead><tr><th width="278.926025390625">フィールド</th><th>内容</th></tr></thead><tbody><tr><td><code>id</code></td><td>ファイル名と一致する安定した一意の識別子。慣例として、トピックパスはすべてこの <code>id</code> を接頭辞にそろえ、変更するときはまとめて更新します。</td></tr><tr><td><code>executablePath</code></td><td>バイナリへのパス。LinuxおよびmacOSでは <code>.exe</code> を外し、インストールルートを確認します。パスとパーミッションの詳細は <a href="/pages/A5iLIuAUfdJuj6FCJnsv">最小構成 (Linux)</a> および <a href="/pages/UwGVpiLHEZV0QBER3Fcy">最小構成 (macOS)</a> をご参照ください。</td></tr><tr><td><code>supportedPlatforms</code></td><td>対象としないOSのエントリを削除</td></tr><tr><td><code>Subscription.Topic</code></td><td>当該プラグインの主たるMQTTトピック。慣例としてプラグインの <code>id</code> を使います。</td></tr><tr><td><code>metadata.mqttTopics.publish</code></td><td>例中の <code>MyWorker</code> をすべて自プラグインの <code>id</code> に置き換えます。設計に応じてトピックを増減します。</td></tr><tr><td><code>metadata.mqttTopics.subscribe</code></td><td><code>MyWorker</code> をプラグインの <code>id</code> に置き換えます。コマンド空間が限定的ならワイルドカードを絞ります (後述)。</td></tr><tr><td><code>startupPriority</code></td><td><code>50</code> はデフォルトの <code>60</code> より少し早く起動します。他構成要素が先に起動しておく必要がある場合にのみさらに下げます。</td></tr></tbody></table>

## 動作の要点 <a href="#how-this-works" id="how-this-works"></a>

**トピック構成:** 以下の3つのトピックパターンが、一般的なコマンド／レスポンス構造になります。

<table><thead><tr><th width="201">トピック</th><th width="115">方向</th><th>用途</th></tr></thead><tbody><tr><td><code>MyWorker/Commands/+</code></td><td>購読</td><td>内向きのコマンド。<code>+</code> は1階層にマッチし、<code>MyWorker/Commands/scan</code> や <code>MyWorker/Commands/reset</code> など、コマンド種別ごとにサブトピックを分けられます。</td></tr><tr><td><code>MyWorker/Responses/+</code></td><td>パブリッシュ</td><td>外向きの結果で、コマンド側のサブトピックに対応します。<code>MyWorker/Commands/scan</code> への応答は <code>MyWorker/Responses/scan</code> へパブリッシュします。呼び出し側は必要なレスポンストピックだけをサブスクライブします。</td></tr><tr><td><code>MyWorker/Status</code></td><td>パブリッシュ</td><td>ヘルス信号、ハートビート、状態変化など。コマンドを送らずにプラグインの生存や状態を監視するために使います。</td></tr></tbody></table>

**主たる `Subscription` トピックの役割:** `MyWorker`（`Subscription.Topic`）は、オーケストレーターがプラグインを識別するために使うトピックです。`metadata.mqttTopics.subscribe` に列挙するコマンド用トピックとは役割が異なります。どちらもサブスクライブしますが、主たるサブスクリプションはエージェントが接続状態を把握するため、コマンド用トピックは呼び出し側がプラグインを操作するためです。

**本番ではワイルドカードを絞る:** `Commands/+` は任意の1階層サブトピックを許します。扱うコマンドが既知の集合に限られる場合は、ワイルドカードではなく明示のトピック文字列に制限します。

```json
"subscribe": [
  "MyWorker",
  "MyWorker/Commands/scan",
  "MyWorker/Commands/reset"
]
```

レスポンス側のパブリッシュも明示トピックに制限します。

```json
"publish": [
  "KeeperLogger",
  "MyWorker/Responses/scan",
  "MyWorker/Responses/reset",
  "MyWorker/Status"
]
```

開発中はワイルドカードが便利ですが、ブローカーが強制できる範囲が広がります。本番では明示リストの方がセキュリティ上タイトです。

**コマンドとレスポンスの対応付け:** トピック命名でルーティングは決まりますが、ペイロードにも相関IDを載せ、特に複数呼び出し元が同時にコマンドを送る場合に応答と元コマンドを対応づけられるようにします。これはバイナリ側の設計責務であり、プラグインJSONやブローカーが強制するものではありません。

**`startupPriority: 50`** はデフォルトの `60` より少し早く起動します。自分より前に起動している必要がある構成要素がある場合、またはエージェント起動直後からプラグインが利用可能であることが期待される場合にのみ、より小さい値を使います。可能な限り早く起動すること自体を競わせないでください。優先度が高いほど、他の構成要素の準備が進む前に自分が起動します。

## デプロイ前に <a href="#before-you-deploy" id="before-you-deploy"></a>

1. 各対象プラットフォーム向けにバイナリへ署名します。WindowsはAuthenticode、macOSはApple Developer IDでの署名と公証、Linuxは運用の署名方針に合わせます。
2. プラットフォーム別バイナリを正しいパスへ配置します。クロスプラットフォームプラグインでは、Windowsは `bin/MyWorker/MyWorker.exe`、LinuxおよびmacOSは拡張子なしの `bin/MyWorker/MyWorker` を、それぞれのエージェントルート配下で同じ相対パスに置きます。
3. LinuxおよびmacOSでは `chmod +x` で実行権限を付与します。
4. 各エンドポイントでJSONファイルを `{AgentRoot}/Plugins/MyWorker.json` に置きます。
5. `MyWorker/Responses/+` や `MyWorker/Status` をサブスクライブする構成要素が、本番前にそれらのトピックのMQTT購読権限を持っているか確認します。
6. エージェントを再起動し、オーケストレーターが登録を読み込むようにします。

## 検証 <a href="#verify" id="verify"></a>

エージェント再起動後、ログで主たるサブスクリプションのトピックが有効になっていることを確認し、プラグインが接続したことを確かめます。続いて、信頼できるプロセスからテストコマンドをパブリッシュし、期待するトピックへレスポンスが届くかを確認します。届かない場合は以下を確認します。

* コマンドのトピック文字列が、プラグインのサブスクライブ内容と完全一致しているか
* レスポンストピックが `metadata.mqttTopics.publish` に含まれているか。欠けているとパブリッシュは黙って拒否され、呼び出し側にはエラーとして見えません
* 呼び出しプロセスに、コマンドトピックへのパブリッシュ権限とレスポンストピックへの購読権限があるか


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/endpoint-privilege-manager/integrations/examples/plugin-command-response-mqtt.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
