AI機能の概要~
AoTは、MCP(Model Context Protocol)ベースのAIエージェントを使って、現場(温室、圃場、公園、建物など、機器が空間に配置された場所ならどこでも)の環境を観察・診断・制御します。AIはあくまでアドバイス役に徹し、機器を動かす操作はすべて実行前にユーザーの承認が必要です(設定だけを変更する編集は例外です。詳しくは「安全性と承認のモデル」の節を参照してください)。
はじめに: スイッチは2つあります~
AIを使うには、別々の場所にある2つのスイッチを入れる必要があります。あえて1つにまとめていません。
| スイッチ | 場所 | オンにすると起きること |
|---|---|---|
| AIサービスを有効化 | 管理 > システム管理 > 一般設定 | AIメニューがナビゲーションに現れ、AIページに入れるようになります。 |
| 内蔵AIを動かす | AI > 接続 > 内蔵AI | 内蔵モデルそのものが動きます — チャットとアドバイス要求、そして誰も呼ばなくても動く作業(定期サマリー、コンテキストのブロードキャスト、天気サマリー、MCPヘルスチェック、リアルタイムアラート)。 |
順序は 一般設定で有効化 → AI > 接続ページでモデル(エージェント)を登録 → 稼働を開始 です。
Claude Desktop などの自分のAIアプリで接続する経路は、このスイッチとは別に動きます。管理 > システム管理 > 一般設定で外部MCPのアクセスを許可し、ユーザーごとのアクセスキーがあれば足ります。内蔵AIはオフのままで構いません。AI > 接続ページの上部で両方の状態を確認し、それぞれの画面へ移動できます。
この「外部MCPアクセス」トグル(管理 > システム管理 > 一般設定 > 外部MCPサーバーを有効化、AIGlobalSettings.mcp_http_enabled)は、MCPサーバーへのリクエストのたびにキャッシュせず毎回確認されます — オフにすると、再起動なしでその場から外部MCP呼び出しがすべて503になり、オンに戻せば同じくらいすぐに復旧します。
- モデルを1つも登録していないと稼働を開始できません。 尋ねる相手がいないままバックグラウンド処理だけが回ると、サイクルのたびにログにエラーが積み重なるだけです。このスイッチは、少なくとも1つのエージェントが有効化されている場合にのみ使えるようになります。
- 最後のモデルを無効化または削除すると、稼働も止まります。 後でモデルを再度有効化しても、自律稼働は黙って再開しません — AIページであらためて開始してください。
- 稼働をオフにすると、チャットとアドバイス要求も拒否されます。 このスイッチは「内蔵モデルが動いている」という意味なので、オフの間は尋ねる相手がいません — AIページの補足行もそう書かれています。ただし1つだけ開いたままです。すでに提出されたアドバイスを決定する操作は(自分のAIアプリがMCP経由で出したものも含めて)AI → リクエスト画面で引き続き行えるため、内蔵モデルを止めているせいで決定待ちの項目が消えることはありません。
AIシステムのアーキテクチャ~
AoTのAIは、2つの経路でツールを使用します。
- アプリ内AIアシスタント — ダッシュボードのチャットアシスタントです。単一のエージェントループがツールカタログ全体を把握し、自らツールを選択・実行します。状態を変更する操作(デバイス制御、エンティティの作成・編集・削除など)は、チャットの承認カードでユーザーが確認したあとにのみ実行されます。
- 外部MCPサーバー —
aot/aot_mcp_server.py(標準MCPプロトコル、stdio/HTTP)。Claude Desktopなどの外部MCPクライアントがAoTのツールを直接呼び出せるように公開します。
ユーザーチャット ─────────┐ 外部MCPクライアント(Claude Desktopなど)
↓ ↓
アプリ内エージェントループ aot_mcp_server.py (stdio/HTTP)
└──────────┬───────────────┘
↓
tool_execution.py — 承認ゲート + 監査ログ
↓
ツールレジストリ (tool_registry.py) — ツール宣言の単一のソース。
このディスパッチマップが呼び出しを実際のハンドラーに解決します
↓
AoTシステム (Daemon / InfluxDB / SQLite)
どちらの経路も同じゲート(aot/tools/tool_execution.py)を通って実行され、同じ レジストリ(aot/tools/tool_registry.py)からツール定義を取得するため、アプリ内 アシスタントと外部MCPクライアントの間で承認ルールもツール一覧も決してずれません。
MCPツール一覧~
外部MCPサーバーと内部のmcp_aotエンジンが公開するツールです。読み取り系ツールと設定編集系ツールは即座に実行されます。制御・スケジューリング・有効化系ツールは、どちらの経路でも承認ゲートを通ります — アプリ内アシスタントのチャット承認カード、または外部MCPサーバーの承認キュー(pending_approval + respond_to_confirmation。詳しくは後述の「MCPサーバーの実行」を参照)です。
2つの層: tools/list とドロワー~
ツールカタログは1枚のフラットな一覧ではありません。全量をそのまま公開すると会話が始まる前だけで約2万トークンかかるため、tools/listが返すのは2つの層だけで、残りは必要になった時点でドロワーを開いて取り出します。
- 常時公開(core) — 28個。 次の一歩を、推測に頼らず踏み出すために欠かせない狭い集合です — 名前解決(
resolve_target)、デバイス検索、値の読み取り、即時制御、承認キューなど(aot/tools/tool_registry.pyの_TIER_ASSIGNMENTテーブル)。 - メタツール4個、coreと一緒に常時公開:
open_drawer(ドロワー1つの中のツール一覧。引数なしで呼ぶと全ドロワーの索引)、get_tool_detail(ツール1つの完全なスキーマを名前で取得)、use_tool(ドロワーのツールを名前で実際に呼び出す — ドロワーのツールを実行する唯一の手段で、open_drawer・get_tool_detailは定義を返すだけです)、respond_to_confirmation(保留中の確認を承認/却下)。 - 残り101個は目的別の8つのドロワーに入っており、
open_drawerを呼んではじめて見えます:device(デバイス操作・状態)、measurement(センサー・環境・天気・エネルギー)、function(Function・コントローラー・シーケンス)、schedule(スケジュール)、record(ノート・掲示板・知識・アドバイス)、space(地図・ゾーン・施設・作物区画)、definition(デバイス定義のCRUD)、system(AI設定・システム状態・診断・画面)。
ドロワーは任意の機能になりました。外部MCP接続では、ドロワーなしでキーのツールセット(次の節)全体を一覧として受け取ります — これが既定です。AOT_MCP_TOOL_TIERING=1(true・yes・onも可)でドロワー構成に戻せます。その場合もキーのツールセットの範囲内で動作し、open_drawer・get_tool_detail・use_toolが再び一覧に出ます。アプリ内AIアシスタントの内蔵ツール一覧はドロワー構成のままです(AOT_AI_BUILTIN_MCP_TIERING、既定オン)。
APIキーごとのツールセット~
APIキーごとに、外部のAIアプリに見せるツールの範囲、つまりツールセットを選びます。キーの権限とは別の設定です — 権限はそのキーで何をしてよいかを、ツールセットは何を一覧に載せるかを決めます。
ツールセットは運用(常にオン)に、チェックした設定モジュールを加えたものです。モジュールひとつが設定作業のひと分野を加え、会話ごとにAIへ送るツール一覧がおおよそ表のサイズだけ増えるため、そのキーの用途に必要なモジュールだけをチェックしてください。
- 運用(常にオン。新しいキーは既定でこれだけを受け取ります — サーバー案内文を含めて約2万1千トークン) — 日々の作業: デバイス・センサー・天気・スケジュール・ノート・区画の参照、デバイスと関数の制御、関数オプション・シーケンス運転時間・既存のシーケンスステップの調整、スケジュール登録、ノート・お知らせ・助言・区画ステージの記録。
| モジュール | 追加される作業 | おおよそのサイズ |
|---|---|---|
plots — 区画と作期プログラム | 区画の作成・編集・複製・分割、ステージの型と案内、作期プログラム | 8.8kトークン |
map — 地図と位置 | 住所、距離、近いものの検索、デバイスの配置、地図図形の削除 | 1.5k |
automation — 自動化の作成 | 関数・シーケンスの作成・削除、シーケンスの1日の計画の一括設定 | 2.0k |
devices — デバイス定義 | デバイスの種類とオプション、入力・出力・GIS入力の作成・編集・削除、スロットの再割り当て | 2.5k |
dashboard — ダッシュボード | ダッシュボード・ウィジェット・タブ | 2.9k |
library — 文書とライブラリ | アーカイブ文書、お知らせの編集・削除、調べた知識の保存、ライブラリソース | 4.4k |
admin — システムとAI設定 | システム更新・ストレージ階層の状態、AIエージェント | 1.3k |
すべてのモジュールをチェックすると以前の運用 + 設定と同じになり、そのように(configuration)保存されます — そのキーは今後追加されるモジュールも受け取ります。モジュール導入前に運用 + 設定だったキーはそれまでと同じ一覧のまま、運用のキーは運用のままです。変換は何も行いません。
管理 > システム管理 > ユーザー一覧のAPIキー欄(AIツール)でキーの発行時にモジュールを選び、あとから同じ画面でキーを再発行せずに変更できます(キーの行のチェックボックスを変えて変更)。変更にはキーの失効と同じ権限(ユーザー編集)が必要で、変更前後のツールセットとモジュール一覧が監査ログに記録されます。新しいキーの発行には、これに加えて直近のログインが必要です。接続済みのアプリは、再接続すると新しい一覧が表示されます。ドロワーを有効にしている場合、ドロワーにもそのキーのツールセットに含まれるツールだけが入ります。
キーがオフのモジュールの設定ツールを呼び出すと、サーバーは呼び出しを拒否し(call_state: refused、reason_code: tool_profile、tool_module: <モジュール>)、そのモジュール名と、誰がどこでオンにするかをメッセージで伝えます。承認待ちには入りません。get_tool_detailとopen_drawerも、ツールセット外のツールやドロワーを「不明なツール」や空のドロワーとして返さず、同じメッセージで答えます。キーの権限でどのみち使えないツール(例: 読み取り専用キーの書き込みツール)の場合は、切り替えても意味がないため切り替えの案内を付けません。その他の拒否(助言専用モード・キーのロール・承認)でも切り替えは勧めません — 助言専用モードはどのツールセットでも変わらないサーバー全体の設定です。ツールセット外のツールの承認待ち項目はツール名を出さずに(中立の表示と分野のみ)表示され、そのキーで却下はできますが承認はできません。サーバーの案内文とget_system_briefは、オンのモジュールと、オフのモジュールごとに何が加わるかを1行ずつAIに伝えるため、AIは「できない」と答える代わりに、どのモジュールをオンにしてもらうかを案内できます。
- ツールセット導入前に発行されたキーは、アップグレード後の最初の起動時に一度だけ割り当てられます: 直近90日間にキーの所有者が設定ツールを呼び出していれば運用 + 設定(全モジュール)、それ以外は運用です。監査ログにはどのキーで呼び出したかが残らないため、人単位で決めます — 同じ人のキーはすべて同じ値になります。割り当て後、キーごとに必要なモジュールへ絞ってください。
- アプリ内のAIアシスタントはツールセットの制限を受けません。内蔵AI自身のサービスアカウントのキー(アプリ内のデバイス制御はこのキーを経由します)も同様で、画面ではこのアカウントのキーにモジュールの選択を表示しません。
- 中央認証で接続した場合は、モジュールを選ぶキーがありません:
aot.configスコープがあれば全モジュール、なければ運用です。 knowledge_searchは、見つけた内容をknowledge_shelveで保存するよう促す案内を、それを使える接続(libraryモジュール、またはアプリ内のAIアシスタント — ノート編集権限がある場合)にだけ付けます。set_output_stateとlist_available_devicesはAPIキーの一覧から外れました — 同じ作業はoperate_device・get_device_list・search_devicesが行います。AOT_MCP_TOOL_PROFILES=0でツールセットを無効にします(以前と同じく、すべてのキーが全一覧を見ます)。AOT_MCP_DEFAULT_TOOL_PROFILEは認証なしで動くサーバーのツールセットです(既定operations。configurationやoperations+plots+mapのような値も使えます)。
名前での指定、複数対象の一括指定、引数の事前確認~
- IDの代わりに名前。
get_output_state・get_device_measurements・get_sensor_detail・get_sensor_readingはデバイス名を、get_zone_sensor_summary・list_plotsはゾーン・サイト名を、get_plotは栽培中の区画の名前・作物・品種を受け付けます。IDもそのまま使え、先に確認されます。名前が複数の対象に当たる場合は1つを選ばず、needs_disambiguationと、場所で見分けられる候補を返します。 - 複数の対象を一度に(最大10個):
device_ids(get_output_state・get_sensor_reading)、loc_ids(get_sensor_detail)、plot_ids(get_plot)、target_names(search_notes)、zone_ids(get_zone_sensor_summary)。応答は{count, results}で、対象ごとに1回呼んだときと同じ形です。 - 引数を先に確認します。 書き込みツールは権限・承認の段階より前に引数を確認します。不足している引数、正しい名前の打ち間違いと思われる引数、
modify_function_optionsの存在しないオプションキーや誤った値は、reason_code: invalid_argumentsと正しい名前の一覧で返ります(get_function_detailが関数のオプションキー・現在値・範囲を先に示します。temperatureのような範囲はキーではなく、その下限・上限のキーを使います) — 助言専用モードでも同じで、そのキーではどのみち実行できない呼び出しならその旨も伝えます。それ以外の不明な引数は無視され、_ignored_argumentsで知らせます。 - 引数が原因で拒否されるときは、そのツールの詳細な
schemaとhint(入れ子の項目の形・判断ルール・例)も一緒に返します。get_tool_detailも1つのツールについて同じ詳細な説明を返します。ツール一覧自体は軽いままで、これらは載せません。 - 大きな結果は応答が大きくならないよう要約形で返します。
list_plots・get_crop_statusは最初の10件のみ(truncated表示)、get_control_stateは画面専用の診断値を省き(detail=trueで戻せます)、get_plotは段階表の案内・目標を省きます。省いたものは_omittedに記します。 get_sensor_readingのスキーマにデバイスIDの一覧を載せなくなりました。デバイスが増えてもツール一覧は大きくなりません。search_devicesは同じ名前のデバイスを示します(same_name_count・where・same_name_groups)。get_spatial_treeをdepthなしで呼ぶと、すべての階層のサイト・ゾーン・施設と、場所ごとのデバイス数を返します。デバイスまで見るにはdepthを指定します。- 区画のステージ: すでに起きた切り替えは
confirm_plot_stage、まだ来ていない境界を動かすのはreschedule_plot_stageです。get_plotがそのステージを提案していなければ、confirm_plot_stageには日付(started_on)が必要です。 - ツールの説明は短くしました。結果の読み方は応答の
_reading欄に載り、AIはそれに従います。
以下の表はどちらの層にあるかにかかわらずツールを説明します — ドロワー列はtools/listには無く、先に開く必要があるツールを示します。引数まで含む完全なツール一覧(ドロワー内のツールを含む)はAIエージェントガイド(docs/ai_guide.md)にあるので、そちらを参照してください — このページでは表を重複して並べません。
観察(読み取り — 即時)~
| ツール | 説明 | ドロワー |
|---|---|---|
get_spatial_tree | すべてのサイト・ゾーン・施設と場所ごとのデバイス数(depthでデバイスまで) | ―(core) |
resolve_target | 場所やデバイスの名前を正確なエンティティへ解決 — コンテナ(子を持つか)かどうかを事前に確認。同じ名前が別々の場所・デバイスに複数あるときは一つを選ばず、候補とそれぞれの位置、その一つだけを指す名前(あれば)を返す — なければ候補のtarget_idを渡す(add_schedule・edit_schedule・create_noteが受け付ける)。内外に重なる同名の図形は一か所とみなして外側を指し、内側はalso_insideで知らせる | ―(core) |
get_device_list | 登録済みの全デバイス(入力・出力・カメラ)の一覧 | ―(core) |
search_devices | 名前や種類のキーワードでデバイスを検索 | ―(core) |
get_sensor_detail | センサーの時系列履歴(最小・最大・平均の統計) | ―(core) |
get_weather | 圃場・ゾーンの現在の天気(気温、湿度、風、降水) | ―(core) |
get_energy_report | 期間・ゾーン別のエネルギー使用量レポート | measurement |
get_cumulative_status | EnvCoordinatorのDLI / GDD累積状況 | measurement |
search_notes | ゾーンやデバイスのノート・メモ・作業記録を読み取る | ―(core) |
get_note_attachment | ノートに添付された写真を実画像として表示(1回の呼び出しにつき1枚) | record |
list_notices | 掲示板の投稿一覧 | record |
get_system_update_status | インストール済みバージョンと最新のGitHubリリースの比較 | system |
list_available_devices | AI判断に使えるデバイス(ネイティブブリッジ) | ―(アプリ内のみ) |
get_sensor_reading | 1つ以上のセンサーの最新値、IDまたは名前で(ネイティブブリッジ) | ―(core) |
記録 / タスク~
| ツール | 説明 | 承認 | ドロワー |
|---|---|---|---|
create_note | 日付のないメモ・ノートをエンティティに作成し、即座に保存 | 不要 | ―(core) |
add_schedule | 人が行う作業タスク(除草、点検、清掃)を登録 | 不要 — config_only: Draft状態のスケジューラージョブを作るだけで、機器は動かしません。人が後でスケジューラー画面で確認するのは、それとは別の手順です。 | ―(core) |
add_schedule_batch | 複数の対象(ゾーンごとなど)へのスケジュールを1回の呼び出しでまとめて登録 | 不要 — add_scheduleと同じconfig_onlyの理由 | schedule |
制御(ユーザー承認が必要)~
| ツール | 説明 | ドロワー |
|---|---|---|
operate_device | バルブ・ポンプ・照明の即時物理制御 | ―(core) |
set_output_state | 出力のオン・オフ切り替え(継続時間の指定は任意、ネイティブブリッジ) | device |
schedule_device_control | 特定の時刻に1回限りのデバイス操作を予約 | schedule |
アプリ内アシスタントでは、上記の制御ツールは、承認カードでの確認を経てはじめて実行されます。外部MCPサーバーから直接呼び出す場合も同種のゲートを通ります — 最初の呼び出しは実行されず、
confirmation_id付きのpending_approvalとして返ってきます。ユーザーがチャット(respond_to_confirmationで処理)またはWebレビュー画面でそのconfirmation_idを明示的に承認または却下したのち、呼び出し側が同じ引数に_confirmation_idを加えて再試行してはじめて実際に実行されます。全体の流れは後述の「MCPサーバーの実行」を参照してください。add_schedule・add_schedule_batchはこのゲートを通りません — 上の「記録 / タスク」表を参照してください。
シーケンス(設定編集には承認不要)~
シーケンスは複数の出力を決まった順序で動かします — かんがいでよくある形で、バルブが順番に切り替わり、ポンプが運転全体にまたがって動きます。以下のツールはシーケンスを読み取り、組み立てます。この節のツール4つ(以下の3つとcreate_sequence_function)はいずれもfunctionドロワーにあります。
| ツール | 説明 |
|---|---|
configure_sequence_day | ある曜日の実行計画全体を1回の呼び出しで設定 — どのデバイスを、どの順序で、どれだけの時間、どれをまとめて動かすか |
modify_sequence_step | 1ステップのグループ・所要時間・単独/合計モード・合計ステップの先行/遅延マージン・実行順序・有効状態・ラベルを、全曜日一括または特定の曜日だけに設定 |
modify_sequence_schedule | 1日の実行時間帯、サイクル周期、シーケンスを実行する曜日 |
シーケンスの設定編集は、承認なしで即座に反映されます。 上記の3つの ツールに加えて
create_sequence_functionとmodify_function_optionsも、 設定を変更するだけで、機器を動かすことはありません。編集が現場で効果を持つのはactivate_functionを経たあとだけで、有効化そのものは引き続き承認の対象です。 受け入れているトレードオフはこうです — すでに有効なシーケンスのスケジュールを 編集すると、承認なしで次回実行が変わります(2026-08-07に決定)。
get_function_detailはシーケンスのステップに加えてweekly_plan(各曜日に実際に何が、実時刻でいつ動くか)を返します。変更を確認するときは、リクエストを繰り返すのではなく、これを読み返してください。
シーケンスはIDの代わりに名前でも指定できます — まずIDが照合され、なければ名前で探します。関数の名前に重複の制限はないため、名前が2つ以上に当たる場合は何も変更されません。代わりに名前が曖昧である旨の応答と、候補(種別・有効かどうか・所属タブつき、最大10件と総件数)が返ります。意図したほうのIDで呼び直してください。
使う前に知っておくとよいことが2つあります。
- 同じスロットに並んだデバイスは同時に動きます。スロットは1つの所要時間を共有します。「この2つのバルブを40分間一緒に開ける」はこうやって表現します。
- 曜日ごとに、どのステップを動かすか・そのグループ・所要時間を上書きできます。 そのため、たとえば木曜の夕方の運転と金曜の明け方の運転を1つのシーケンスでまかなえます。曜日が違うというだけの理由で2本目のシーケンスを作る必要はありません。
modify_function_optionsはシーケンス(や他のトリガー)には効きません — それらの設定はcustom_optionsではなくデータベースの列だからです。呼び出すと、上記のツールを使うよう案内して拒否されます。
呼び出し状態(call_state)~
tools/callのすべてのレスポンスにはcall_stateが含まれます。各ツール固有の statusの語彙(modified、created、deleted、configured、successなど)を 知らなくても、その呼び出しが実際に実行されたかどうかをこれで判断できます。
| 値 | 意味 | クライアント側の対応 |
|---|---|---|
executed | この呼び出しで実行済み(読み取りツールも含む) | 結果を報告する |
already_executed | ユーザーが承認した時点でサーバーが既に実行済み | 同梱のresultを報告する。再度呼び出さない |
pending_approval | 未実行、人の承認待ち | ユーザーを承認ページに案内して待つ |
approval_rejected | ユーザーが却下した | 実行しない。アドバイスに切り替える |
approval_expired | 承認の有効期限が切れた | あらためて承認を求める |
refused | 別の理由で拒否された(レート制限、引数の不一致など) | reason_codeを読んで説明する |
failed | ツールがエラーで終了した | エラーを報告する |
既存のstatusの値は変わりません — コードや稼働中の設定は既にそれで分岐しているため、これは軸を再定義するのではなく新たに1本追加するものです。
状態を変える呼び出しが適用されなかった場合(executed・already_executed以外のすべて、または承認時の実行が失敗した場合)、レスポンスにはperformed: falseと短い_readingも含まれます。ユーザーに適用されていないこと(pending_approvalなら、まだ人の承認待ちであること)をはっきり伝え、対象はIDではなく名前で示す、という内容です。いくつかのツールはエラーではなく独自のstatusの語で「実行しなかった」ことを伝えます。状態を変えるツールでは、これらも適用されなかったものとして扱います: refused(呼び出し状態refused)、rejected・quota_exceeded・not_found・target_not_found・orphan_archive・needs_disambiguation・ambiguous・unavailable(呼び出し状態failed)。そのため、呼び出し品質指標の拒否率は権限・ポリシー・人による拒否だけを数えます。
デバイス命令(operate_device・set_output_state・schedule_device_control)は例外です。命令がすでにデバイスに届いた可能性がある失敗(タイムアウト、通信エラー、送信後のコントローラーエラー)では、performedはfalseではなく"unknown"になります。タイムアウトは呼び出し側が待つのをやめたという意味にすぎないため、再実行の前に現在の状態を確認し(get_output_state、スケジュールならsearch_schedule)、確認できるまでは実行された・されなかったのどちらとも伝えません。何も送信する前に止まった失敗(存在しないデバイス、不正な引数、拒否)はperformed: falseのままです。アプリ内のAIも同じ結果を同じ意味で読み、Webの承認画面は単なる失敗ではなく「コマンドは送信しましたが、反映されたかは確認できませんでした — 機器の状態を確認してください」と表示します。
関数・入力をオン/オフすると、まず設定を保存してから実行中のコントローラーに知らせます。コントローラーが確認を返さない場合(停止中や処理中の可能性があります)、レスポンスは保存された値をそのまま含み、呼び出し状態もexecutedのままですが、performedは"unknown"になります。今オンになった・オフになったとは伝えず、設定は保存されたが実際の動作に反映されたかはまだ確認できていないと伝えます。get_active_functions_summaryは保存された設定しか示さないため、これを確認する手段にはなりません。
submit_adviceのレスポンスも、求められた変更ではなく提案だけが保存されたことを明示します。1つの名前が複数の場所やデバイスに当たる場合は、その候補ごとにwhereがあり、IDを使わずに区別できます(距離の照会の候補にはありません)。
拡張アプリ内アシスタントツール~
上記のツールに加え、アプリ内AIアシスタントは(そのうちcoreのものは外部MCPサーバーも直接)エンティティの組み立て・自動化・知識のための追加ツールを使います。状態を変更するツールの多くは承認が必要ですが、以下でconfig_onlyと記したものは不要です — 「安全性と承認のモデル」の節を参照してください。
- 入力/出力の管理:
list_device_types、get_device_type_options、create_input・modify_input・delete_input、create_output・modify_output・delete_output、get_device_measurements - Function(自動化):
get_function_list、get_function_detail、create_function、create_sequence_function(config_only)、modify_function_options(config_only。トリガーには使えません — 上記のシーケンスの節を参照)、activate_function・deactivate_function・delete_function、加えてシーケンス用ツールconfigure_sequence_day・modify_sequence_step・modify_sequence_schedule(いずれもconfig_only) - スケジュール台帳:
search_schedule、edit_schedule、delete_schedule - 地図(GIS):
list_geo_maps、get_device_location、set_device_location、delete_geo_shape、list_unbound_slots(デバイスのない場所を確認)、rebind_device(1台のデバイスが占める地図上の全スロットを別のデバイスへ移す) - GIS入力(地図レイヤー):
list_gis_inputs、create_gis_input(config_only— 常に非有効の状態で作成)、modify_gis_input・delete_gis_input・activate_gis_input(承認が必要) — VWorld/Google/OpenWeatherなどの地図レイヤー提供元を管理 - 施設/設備の照会:
get_facility_capacity(施設の冷暖房能力・容積・換気・かんがい設計の要約)、get_map_equipment(地図に描かれた設備のサイト/ゾーン別かんがい設計要約。スプリンクラーと点滴かんがいは分けて集計)、get_map_equipment_detail(個々のスプリンクラーの位置・間隔・散水半径、配管ごとの詳細 — 要約で足りないときだけ) - 掲示板:
create_notice・modify_notice・delete_notice - AIエージェント管理:
list_ai_agents— これはcoreなので、アプリ内だけでなく外部MCPサーバーのtools/listにもすでに含まれています。list_ai_entries、create_ai_agent(config_only)、modify_ai_agent・delete_ai_agent(承認が必要) - 知識ライブラリ:
knowledge_search、knowledge_shelve、list_library_source_types、smartfarmkorea_lookup、configure_library_source - ドキュメントストレージ階層:
get_storage_tier_status、search_archives、get_archived_document、archive_note・restore_note_from_archive・delete_archive・set_document_tier— 古いノートのための任意のコールドアーカイブです。archive_noteはノートの内容を圧縮した長期保存領域にコピーしてtier 3として印を付けるだけで、元のノートはそのまま残ります。delete_archiveはそのアーカイブされたコピーだけを削除し、ノート自体には触れません。この機能には専用画面がなく、AIツールからのみ使えます。 - 診断/その他:
analyze_system_failure、get_local_time、get_tool_detail、read_manual、get_detailed_manifest、ask_user
ツールの単一の正本は
aot/tools/tool_registry.pyです。ツールが追加・変更されたときは、このページではなくそのファイルが正となります。引数まで含む完全なツール一覧(ドロワー内のツールを含む)はAIエージェントガイド(docs/ai_guide.md)を参照してください。
デバイスごとのAI対象トグル~
設定 -> 入力 / 設定 -> 出力の各デバイス設定モーダルには、AI判断に含めるトグルがあります。
- オン(既定): その入力/出力はAI判断・制御ツール(空間ツリー、デバイス照会、センサー/制御ツールなど)から見えます。
- オフ: そのデバイスはこれらのツールの照会や制御対象から除外されます。機密性の高いデバイスや、AIに絶対に触らせたくないデバイスをデバイス単位で隠すのに使います。
新規に作成した入力・出力は、この設定がデフォルトで有効になっています(is_ai_enabled=True)。
安全性と承認のモデル~
状態を変えない読み取りツールは即座に実行されます。書き込みツールは2つに分かれます。
- 承認が必要(変更・物理制御): デバイス制御(
operate_device、set_output_state、schedule_device_control)、入力/出力/Function/掲示板の作成・編集・削除、modify_gis_input・delete_gis_input・activate_gis_input、modify_ai_agent・delete_ai_agent、地図の配置変更(set_device_location、delete_geo_shape)、デバイスの置き換え(rebind_device)、configure_library_sourceなど。 - config-onlyな書き込み(承認免除):
add_schedule、add_schedule_batch、create_gis_input、create_ai_agent、create_program、modify_program、create_sequence_function、modify_function_options、modify_sequence_schedule、modify_sequence_step、configure_sequence_day。これらはそれ自体では機器を動かさないため、承認なしで即座に保存されます — このうち大半(create_gis_input、create_ai_agent、シーケンス系ツールなど)は、作られるものが常に非有効の状態で、実際にそれを有効にする別の段階が用意されており、その段階は引き続き承認の対象です。たとえばcreate_gis_inputは即座に保存されますが、activate_gis_input(承認が必要)を経るまでオフのままですし、シーケンスのスケジュールは自由に編集できても、実際に現場で動くのはactivate_function(承認が必要)を経たあとだけです。create_note・knowledge_shelveは記録の書き込みです — これらも承認なしで保存され、有効化の段階はなく、知識は人が確認するまで未確認・非正として扱われます(後述のAI知識の節を参照)。それでも書き込みなので、Webのノート画面と同じ設定編集の権限が必要で、読み取り専用キーとアドバイス専用モードでは拒否され、グループの範囲に従います。承認免除は権限免除ではありません。アプリ内アシスタントでもMCPでも、config-onlyを含むすべての書き込みは、依頼した人にその権限がある場合にだけ実行され(ノート・知識と地図編集 — 地図の図形の削除・装置の配置、Webの地図編集と同じ — は設定編集の権限、区画・ステージ記録・区画の資源・作期プログラム・区画日誌はWebの区画画面と同じ区画編集の権限、それ以外は制御の権限 — 既定の役割ではMonitor・Guest・Kioskは不可)、対象をIDで指定しても名前で指定しても、その人のグループの範囲内でだけ実行されます。グループの判定は引数だけでなく、ツールが実際に変更する対象(解決された装置・関数・スケジュール・ステップ)に対して行われるため、名前で指定する、スケジュールやステップのIDを渡す、他グループのリソースを本文に書く、といった方法では回避できません。保留中のリクエストを承認するには、そのリクエストと同じ権限が必要です(区画のリクエストは区画編集、地図編集は設定編集、それ以外は制御 — Webでもrespond_to_confirmationでも同じ)。承認者が対象のグループ外であれば、リクエストは実行されず、判断できる別の人のために保留一覧へ戻ります。予約ジョブは実行のたびに、その責任者(作成した人、AIが提案した予約は承認した人)の権限とグループで改めて確認します — その間に権限やグループを失っていれば実行せず、失敗として記録します。背後に人がいないバックグラウンドのAI処理(定期要約など)は例外です。
承認が必要な操作は即座には適用されません。アプリ内アシスタントでは、チャット上に承認カードとして提示され、ユーザーが承認してはじめて実行されます。外部MCPサーバー経由では、pending_approvalレスポンス(キューに入ったconfirmation_id)として返り、ユーザーがそのidを明示的に承認または却下してはじめて先に進みます — どちらの経路でも、ユーザーが却下すれば何も変わりません。
Webのリクエスト画面(AI → リクエスト)で承認すると、その場で即座に実行されます。 以前は、承認しても許可証が出るだけでした — 人がAIのところへ戻って伝え、AIがもう一度呼び出す必要があり、チャットモデルは話しかけられたときにしか動かないため、この往復をAI自身では完結できませんでした。現在はサーバーが、確認と一緒に保存された引数をそのまま使って実行するため、承認画面に表示された内容と実際に実行される内容がずれることはありません。AIが後で同じconfirmation_idで再度呼び出しても、二度目の実行にはならず、その保存済みの結果が返るだけです。取り消せない物理制御(バルブ、ポンプ)だけは、承認画面でもう一段階の確認を求めます。
ダッシュボードウィジェット(aot/widgets/widget_mcp_review.py、js/common/aot-mcp-approval.js)でも同じ承認キューを扱えます。1件ずつ、またはまとめて承認・却下でき、修正してから承認(保存された引数を直してから実行)にも対応します。物理制御はここでも、もう一段階の確認を求められます。
AIの記録~
AI → 記録(/ai/manage)は、AIが行ったことを振り返る場所です。タブはツール呼び出し、会話、エラー報告、呼び出し品質の4つです。
呼び出し品質~
呼び出し品質タブは、接続されたAIがツールをどのように使ってきたかをまとめます。ツール呼び出しタブと同じ記録から計算するため、別に保存するものはなく、このシステムの外に送られるものもありません。
期間(24時間・7日・30日)と、必要なら接続方式(HTTP経由のMCP、このコンピューター上のMCP、REST API、内蔵AI)を選びます。1行に1つの数字が表示されます。
- 呼び出しのまとまり — 1つの会話の中で、90秒未満の間隔で続いた呼び出しです。サーバーには質問の区切りが見えないため、まとまりは質問の近似にすぎません。まとまりあたりの呼び出し数(中央値・90%)と、10回以上のまとまりの割合を合わせて示します。
- 同じツールをすぐにもう一度呼んだ割合と最長の連続 — ツールがAIに必要なものを返せなかったことを示すサインです。
- ツールや対象の検索から始まったまとまり、ツール一覧を開いて実際に使った割合。
- 呼び出しの間隔(中央値・90%) — 呼び出しの合間にAIが考えている時間のおおよそです。
- 照会時間(中央値・90%) — 実際に実行された読み取り呼び出しだけを数えます。
- 失敗・拒否・承認待ちの呼び出し、空の結果(推定)、対象を聞き返した呼び出し、サイズ上限に合わせて短くした応答。「対象が見つからない」と答えた呼び出しや、どの対象かを聞き返した呼び出しは、失敗ではなく空の結果・聞き返しとして数え、その時間は照会時間に含めます。
下の表は、同じ数字をツールのドロワー別に分けて示します。この画面にはツール名を表示しません。
知っておくべき限界:
- 人が承認したあとにサーバーが実行した変更は含まれません。
- 応答サイズには画像を含めません。
- この計測を加える前に記録された呼び出しは除かれます。計測された呼び出しの割合も表示されるので確認できます。
同じ数字は、ツール別の内訳も含めてGET /api/v1/mcp/quality?days=1|7|30&transport=(ログ閲覧の権限が必要)でも取得できます。応答にはユーザー名・会話キー・引数は含まれません。
AOT_MCP_QUALITY_LEDGER=0にすると計測欄を埋めなくなります。ツール呼び出しの記録そのものは従来どおり残ります。
AI知識~
AI -> 知識ページ(/ai/library)はAIの回答の根拠を集めておく場所で、タブが 2つあります。知識タブにはAIが引用できる項目がすべて並び、データソース タブにはその知識の入り口 — 文書(PDF/テキスト)、WebのURL、REST API、内部クエリ、 公共データフィード — が並びます。ソース行の2列目は同期状態(同期済み・同期失敗・ 未同期、その都度照会するソースなら「都度照会」)で、最終同期の時刻はその欄に マウスを乗せるか、ソースの設定で見ます。今すぐ同期も設定にあります。
知識はどこから来るか~
ライブラリには4種類のものが存在し、AIはそれぞれを異なる形で引用します。
| 出どころ | 何であるか | AIの引用の仕方 |
|---|---|---|
| 権威(Authoritative) | 同期される公共データフィード(例: RDA、Nongsaro) | ソース名を添えて事実として述べる |
| 人が入力したもの | あなたが入力した、またはアップロードした文書 | 信頼できる — あなた自身がソース |
| データから導いたもの | このシステム自身の測定値から算出したもの | 一般則としてではなく、ここでの観察として提示する |
| AIが整理したもの | AIが調べた、または導き出して保存したもの | 人が確認するまで未確認のノートとして明示 |
AIは自らライブラリに書き込むこともできます。何かを調べたときは要約を保存し、 次の質問がゼロから始まらないようにします。こうしたノートは常に未確認の状態で 入り、常にそうと明示されます — モデルが書き忘れても、サーバー側がその明示を 付け足します。ライブラリに登録されたソースから写したノートの場合は、引用に そのソース名も添えられます — 依然として未確認ですが、確かめに行く先がある ということです。
AIが書いたものを確認する~
AIが書いたノートのうち確認を待っているものがあると、知識タブの一番上に1行の お知らせが出ます。それだけ表示を押すと、一覧が「確認が必要なもの」に絞り 込まれます。項目を押して詳細を開き、ソースリンクがあれば開いて原文を確かめてから、 保存して確認(誤りがあれば直してから)または取り下げを押します。確認する ことがそのノートを「未確認」から引き上げる唯一の方法です。ソースリンクのない ノートにはリンクが出ません — 照らし合わせる原文がないということです。取り下げは やり直せます。取り下げたノートはよけた項目も含めるで一覧に再び現れ、 再有効化を押すと「確認が必要なもの」に戻ります — 取り下げを解くことは、 確認を済ませたことと同じではないからです。
知識タブの下の知識の設定 → 確認済みの知識のみ引用(既定はオフ)は、AI自身の 未確認ノートをAIが引用しないようにします。権威ある知識と手入力の知識は影響を 受けません。
閲覧と追加~
知識タブの一覧は1行に1項目(タイトル・信頼度)で、既定では人とAIが書いたもの だけを載せます。ソースから同期した資料はタイトルがすべてソース名で、混ぜると見分け られないため、出典の絞り込みで別に選ぶか、データソースタブで管理します。タグは項目の 詳細で見ます — 検索し、出どころ・状態・タグで絞り込み、古くなったものは項目の 詳細から取り置きます(取り置いても行は残ります。AIの手が届かなくなるだけで、 状態の絞り込みで取り置いた項目も表示すれば戻せます)。
知識を追加は、AIのやり取りやソース登録を経ずに、あなたが既に知っていることを 書き込みます。ここに書いた内容は確認済みとして扱われます — あなたが出典です。
知識ダイジェスト・パイプライン~
文書やWebのURLのような長い文章のソースは、登録時に一度だけ前処理されます。
- ソースをチャンクに分割します。
- 各チャンクをダイジェスト化(LLMによる要約 + キーワード抽出)し、
ai_knowledge_chunkテーブルにキャッシュします。 - クエリ時にはLLM呼び出しは発生しません — 検索は純粋なDB照会と決定的な検索だけなので、回答は速く、コストもかかりません。
範囲はサイトではなくタグで決まる~
ここが変わりました — ライブラリは農場全体で共有です
かつて知識はfacility_idで絞り込まれており、このページの旧版には、あるサイト 向けに登録した文書は別のサイトには決して出てこないと書かれていました。それは もう正しくありません。 ライブラリはフラットな、農場全体で共有するカタログです — どの項目もどの質問に対しても検索対象になり得て、関連性はタグとキーワード スコアリングで決まります。
ライブラリを機密性の境界として扱わないでください。このAIを使う全員に見せたく ないものは、ライブラリに入れないでください。
範囲は代わりにタグで決まります — 自由記述のテキスト(「大根」「北棟」 「橋A」など)で、実際に自分が管理している単位を使えます。AoTは農業専用では ないため、決まった語彙はありません。タグこそが、クエリを正しい主題へ絞り込む 手段です。
地域を選ばない組み込みソース~
組み込みソースのほとんどは韓国の公共データ(RDA、Nongsaro、NCPMS、 SmartFarmKorea)で、その提供元のAPIキーが必要です。それ以外の地域でも、 2つの組み込みソースはどこでもキーなしでそのまま使えます。
| ソース | 何に答えるか |
|---|---|
| FAO ECOCROP(EXT-GL-01) | 2,500種以上の生育温度、降水量、土壌pH、標高の限界 |
| Open-Meteo(EXT-GL-02) | 世界的な予報、深さ別の地温/土壌水分、基準蒸発散量(ET₀)、過去の気候 |
Open-MeteoはAoT自身の天気ツールが届かない隙間を埋めます。get_weatherは この設置に配線された天気センサーしか読めず、get_weather_forecastは韓国限定 (気象庁)です。センサーがない場合や韓国の外では、これが唯一の天気の根拠に なります — そして土壌の値とET₀は、どんなセンサーを持っていてもここから 供給されます。
ソースの画面にも書かれている制約が2つあります。Open-Meteoのキーなしの経路は、 規約上は非商用の用途に限られます — 商用で使うなら、Open-Meteoのキーを取得して ソースに入力してください。そうすると商用のエンドポイントへ照会します(キー欄が 任意なのはこのためだけです)。そしてECOCROPの数値は「この種はこの気候で育つか」に 答える適合範囲であり、制御の目標値ではありません。どちらも出典の表示 (CC BY 4.0)が必要で、ソースに既定で入っています。
それ以外は、ライブラリは逆方向に埋まっていきます — あなた自身の文書、 Webページ、REST API、そしてAIが作業中に調べて棚に上げたもの。
データの出典表示~
2つのグローバル組み込みソースはどちらもCC BY 4.0のデータです。このライセンス は、データを表示する場所に出典表示を添えることを求めているため、AoTは2か所で それを行います。
- AI知識ページ — データソースタブの一覧の下に「データ出典」の行があり、 有効化しているソースを網羅します。
- AIの回答 — クエリの応答には出典表示のテキストが含まれるため、AIが その値を引用する際に含めます。
| ソース | ライセンス | 出典表示 |
|---|---|---|
| Open-Meteo | CC BY 4.0(無料枠は非商用限定) | Weather data by Open-Meteo.com |
| FAO ECOCROP | CC BY 4.0 | FAO ECOCROP |
商用利用について
Open-Meteoの無料エンドポイントは、その利用規約により非商用利用に限定 されています(サブスクリプションや広告のあるサービス、商用製品への組み込みは 商用とみなされます)。商用の生産者・サービスは Open-Meteo APIキーを取得し、ソース設定に 入力してください — キーがあれば、AoTは商用エンドポイントを問い合わせます。
出典表示のテキストは、ソース設定(歯車アイコン)の出典表示欄で上書きできます。 空欄のままなら、組み込みの既定文が使われます。
MCPサーバーの実行~
外部MCPクライアント向けの標準MCPサーバーです。アプリの起動時に自動でウォームスタートされ、手動で実行することもできます。
# stdioモード(既定) — 同じマシン上のローカルクライアント
python3 /opt/AoT/aot/aot_mcp_server.py
# HTTPモード — リモートクライアント(既定ポート5700)
python3 /opt/AoT/aot/aot_mcp_server.py --http --port 5700
HTTPモードは、2つの経路を同時に提供します。
| パス | 内容 | 利用者 |
|---|---|---|
POST /mcp | MCP Streamable HTTP(標準トランスポート) | Claude Desktop/Code、Cursor、あらゆるMCPクライアント |
GET /mcp/info、GET /mcp/tools/list、POST /mcp/tools/call | 独自REST | ChatGPT Custom GPT(OpenAPI Actions)、curlでの確認 |
標準クライアントに必要なのはURLとAPIキーだけです — 中継スクリプトは不要です。OAuth 認可サーバーでログインするクライアント(claude.ai のコネクタなど)は中央認証で接続することもできます。
claude mcp add --transport http aot https://<host>/aotmcp/mcp \
--header "X-API-KEY: <base64 api key>"
GET /mcpは405を返します。このサーバーはサーバーからクライアントへのSSEストリームを提供していません。waitressを4スレッドで動かしているため、1本の保持接続がツール呼び出しを飢餓状態にしてしまうからです。仕様上はこれも許されており、将来サーバー起動の通知を送る先になる予定です。
REST APIを残しているのは、通常プランのChatGPT Custom GPTがMCPサーバーを登録できないためです — OpenAPI Actions経由でしか接続できません。
中央認証(OAuth アクセストークン)~
HTTP サーバーは API キーのほかに、OAuth 認可サーバーが発行したアクセストークンも受け付けられます。たとえば AoT 中央認証では、スタッフのアカウント1つで一度ログインし、複数の AoT 現場に接続します。このとき AoT はリソースサーバーです。ログイン・同意・トークン発行は認可サーバーが行い、AoT はトークンの署名・発行者・対象(aud)・有効期限・失効リストだけを確認します。API キーはどちらの場合もそのまま使えます。
特定のネットワークやドメインには縛られません。設定 > 一般 > AIサービス > MCP認証 > 設定する で設定します。
| 欄 | 入力する値 |
|---|---|
| 中央認証 | オンにすると、API キーに加えてアクセストークンも受け付けます |
| 認可サーバー | 発行者アドレス(https)。署名鍵をここから取得するため、このサーバーから届く必要があります |
| MCP公開アドレス | AI クライアントが接続するアドレス(例: https://farm.example.com/mcp)。トークンは正確にこのアドレスを対象にしている必要があります。そのアドレスの /mcp と /.well-known/oauth-protected-resource を MCP サーバー(ポート5700)へ転送してください |
| Web公開アドレス | AoT を開くアドレス。アカウント連携の後にここへ戻ります(Google 連携と共通の値) |
| クライアントID・シークレット | このサイトを認可サーバーに登録するときに発行されます。アカウント連携にだけ使います |
画面には認可サーバーに登録する値(リソース = MCP公開アドレス、リダイレクトURI、スコープ)が表示され、チェックする で保存前に認可サーバーと署名鍵に届くか確認できます。同じ配備テンプレートを複数台で使うときは、環境変数 AOT_MCP_CENTRAL・AOT_MCP_CENTRAL_ISSUER・AOT_MCP_PUBLIC_URL・AOT_MCP_LINK_CLIENT_ID・AOT_MCP_LINK_CLIENT_SECRET が画面の値より優先されます。
トークンの持ち主は認可サーバーのアカウントで、AoT のユーザーではないため、一人ずつ一度だけ連携します。AoT に本人としてログインし、同じ画面で自分のアカウントを連携を押してください。連携するまでは AI は接続できますが、ツールを呼ぶと連携方法の案内だけが返ります。メールアドレスが同じでも自動では連携しません。
トークンでできることは、トークンのスコープを連携したユーザーのロールで絞った範囲です。aot.read(必須)は読み取り、aot.control は機器の操作、aot.config は設定の変更と全設定モジュール(運用 + 設定)です。状態を変える呼び出しは API キーと同じく承認を経ます。
ChatGPT Custom GPTを接続する~
上記の3つのRESTパス(/mcp/info、/mcp/tools/list、/mcp/tools/call)を OpenAPI Actionとして登録します。ActionsつきのCustom GPTを作成するには 有料のChatGPTプラン(Plus/Team/Enterprise/Pro)が必要です — 無料アカウントは この経路をまったく使えません。
- APIキーを発行する —
管理 > システム管理 > ユーザー一覧で、自分のアカウント用に新しいAPI キーを生成します(「ChatGPT」のような名前にしておくと、あとでこの接続だけを 取り消せます)。このGPTが読み取り専用でよいなら、発行時にスコープreadonlyを選んでください — 書き込み系ツール呼び出し(ノート・知識を含む)はサーバー側で拒否 されるため、Custom GPTの設定ミスでデバイスに誤って触れることがなくなります。 複数人が使うなら、1人に1つずつキーを発行してください — 監査ログで誰が何を 呼び出したかがわかり、漏えいしたキーも他の全員を止めずに失効できます。 このGPTが設定作業をしないなら、AIツールは運用だけにし、するなら必要な モジュールだけをチェックしてください(ツールセット)。 - HTTPモードが有効で到達可能なことを確認する — サーバーは
--http --port 5700で稼働している必要があり、ChatGPTがそのポート(または リバースプロキシが公開しているパス)に到達できる必要があります。まず認証なしで 確認してください(バージョンとツール数だけを返し、キーは不要です)。 - GPTを作成する: ChatGPTでExplore GPTs → Create → Configureに進みます。 名前と説明を入力し、Instructionsには少なくとも以下を貼り付けてください — そのまま使うか、自分のサイトに合わせて調整します。
You are an assistant for this AoT system: you observe status, advise, and
can register device-control requests when asked.
- Don't call listTools out of habit. The full tool catalog is a large
response that eats into the conversation budget. Call it once early to
learn tool names and arguments, then call only the tools you need.
- Prefer narrow tools. For a single device or zone, use a tool that
targets just that instead of a broad summary tool.
- When calling callTool, always JSON-encode `arguments` into a string.
E.g. not {"zone_name": "North Field"} but
"{\"zone_name\": \"North Field\"}". Empty is "{}".
- Every tool response carries call_state. Judge success/failure from that
field alone — each tool's own `status` field uses different words:
executed / already_executed → done, relay the result
pending_approval → not yet run, tell the user to approve it
approval_rejected → rejected, don't retry — offer advice instead
approval_expired → approval window expired, ask again
refused / failed → refused or errored, relay the reason
- If a state-changing request comes back pending_approval, don't retry it
yourself — tell the user to approve it on the web approval screen.
- Answer in plain language, without jargon.
- Actionを追加する: 同じ画面の下のほう、Actions → Create new action で、以下のスキーマを貼り付けます(
<host>を実際のアドレスに置き換えて ください)。
openapi: 3.1.0
info:
title: AoT MCP
version: "1.0.0"
servers:
- url: https://<host>:5700
paths:
/mcp/tools/list:
get:
operationId: listTools
summary: List available tools and each tool's argument schema.
responses:
"200": { description: OK }
/mcp/tools/call:
post:
operationId: callTool
summary: Call one tool by name with arguments.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name:
type: string
description: A tool name returned by listTools
arguments:
type: string
description: >-
Tool arguments serialized as a JSON object string.
E.g. "{\"zone_name\": \"North Field\"}". Empty is "{}".
responses:
"200": { description: OK }
- 認証を設定する: Authentication → API Key → Auth Type
Custom→ Header nameX-API-KEY→ 値は手順1のAPIキー(base64)です。 - ⚠️
argumentsは文字列として宣言してください — オブジェクトにしては いけません。 ツールは100種類を超えるため、その引数の形をすべて1つの OpenAPIスキーマに宣言することはできません。argumentsを自由形式の オブジェクトのままにしておくと、ChatGPT Actionsは埋められないフィールドを 黙って落としてしまいます(実際に起きた事例、2026-08-09:list_devices_in_area呼び出しにはarea_nameが必須でしたが、リクエスト本文にはargumentsキー自体が まったく入っていませんでした)。上記のように文字列として宣言しておけば、 これはすでに回避できます — 手順3のInstructionsも同じ理由から同じルールを 念押ししています。 - 保存して確認する: 共有するつもりがない限り、可視性はOnly meの ままにしておきます。チャットで「状況を教えて」のように尋ねてみて、 ツール呼び出しと応答が返ってくれば接続成功です。
- この経路でも、状態を変更するツールは即座には実行されません。 最初の 呼び出しは
confirmation_id付きのpending_approvalとして返り、ChatGPTは それをユーザーに提示し、ユーザーがWeb承認画面で承認したのち、同じ呼び出しに_confirmation_idを加えて再試行してはじめて実際に実行されます。Custom GPT の中で自動的に再承認される仕組みはありません。承認はAI → リクエスト (/ai)画面の一番上「承認待ちの制御リクエスト」で行います。AIが出した スケジュールの提案とアドバイスも同じ画面で決定します。
接続できないとき
| 症状 | 確認すること |
|---|---|
| 「unauthorized」/ APIキーエラー | 手順5で貼り付けたキーの前後に余分な空白がないか、キーが失効していないか |
| Actionが保存できない | 手順4のスキーマを丸ごと貼り付けたか — 波かっこが途中で切れていると保存に失敗します |
| 「そのツールが見つかりません」と言い続ける | GPTが先にlistToolsを呼んでいません — 「まずツール一覧を確認して」と促してください |
| 読み取りはできるが何も制御できない | 想定どおりです — 書き込みは常に人による承認を経ます(手順8) |
| 名前をもとにした質問に妙な答えが返る | get_system_update_statusでバージョンを確認してください — 下記の注記を参照 |
このページで扱っている地図関連のバグ修正(
get_weatherの名前検索が常に 同じ間違ったシェイプに当たる、get_spatial_treeのフィルターが効かない、 ゾーンが階層クエリから消える)は、AoTアプリv26.08.8以降に含まれています。 接続した直後に一度get_system_update_statusツールを呼び、インストール済み バージョンを確認してください — 古いインストールでは、圃場/ゾーン名で尋ねた 質問が古い誤った答えを返すことがあります。
Claude Desktopを接続する~
claude_desktop_config.jsonに追加します。
{
"mcpServers": {
"aot": {
"command": "python3",
"args": ["/opt/AoT/aot/aot_mcp_server.py"],
"env": { "AOT_MCP_API_KEY": "<base64 api key>" }
}
}
}
stdioでも既定でAPIキーが必要です。管理 > システム管理 > ユーザー一覧で発行したキーをenvのAOT_MCP_API_KEYに入れてください — ないと接続直後に認証エラーで拒否されます(認証を無効にするにはAOT_MCP_REQUIRE_AUTH=0)。
ここでも、状態を変更するツール呼び出しは即座には実行されません(
aot/tools/mcp_safety_gate.py)。最初の呼び出しはconfirmation_id付きのpending_approvalとして返り、ユーザーは同じ会話の中、またはAI → リクエスト画面(/ai)上で明示的に承認または却下する必要があり、これはrespond_to_confirmationを通じて処理されます(/api/v1/mcp/review_pageは今も存在しますが、/aiへのリダイレクトになっただけです — ブックマーク互換のためです。監査ログ自体はAI → 記録(/ai/manage)の「ツール呼び出し」タブに移り、「会話」「エラー報告」「呼び出し品質」タブと並んでいます)。承認しただけでは何も実行されません — そのあと_confirmation_idを加えて同じ呼び出しを再試行してください。呼び出し元のAIには、この承認を自分で決めたり偽装したりする手段がありません。AOT_MCP_WRITE_ENABLED=0を設定すると、書き込み系ツールを(ノート・知識も含めて)一律拒否します(アドバイス専用モード。submit_adviceは引き続き使えます)。締め切りは2段階あります — 既定で人が承認するまで15分(AOT_MCP_CONFIRM_TTL_SEC)、承認された瞬間からあらためて5分で実行(AOT_MCP_APPROVED_TTL_SEC)です。制御ツールを引き続き公開しているため、このサーバーは信頼できるクライアントにのみ接続してください。