※お役に立てたらストック、いいねをよろしくお願いします!!
<📝本記事のターゲット層>
- AI Agentを業務システムや社内DBにつなげたい開発者
- MCPで業務データ参照や社内システム連携を始めたい人
- いきなり更新系Toolを作ることに不安があるテックリード
- read-only API、DB権限、監査ログ、個人情報マスクの設計観点を整理したい人
- C# / ASP.NET Coreで読み取り専用連携の実装例を知りたい人
「AI Agentに業務システムを触らせたい」
この話を聞くと、つい最初に思い浮かぶのは、注文更新、顧客登録、問い合わせ対応、在庫調整のような「業務操作の自動化」かもしれません。
ただ、筆者はここで一度ブレーキを踏んだほうがよいと考えています。
業務システムには、本番データ、個人情報、契約情報、在庫、請求、権限、監査ログなど、壊すと困る情報が詰まっています。そこへ最初から更新権限を渡すと、AI Agentの便利さより先に、誤更新・情報漏洩・監査不能といったリスクが前に出てきます。
この記事の主張はシンプルです。
AIに業務システムを触らせるなら、まず“読めるだけ”から始めましょう。
ここでいうread-onlyは、単に「更新しない」という意味だけではありません。AIが安全に読める範囲を決め、返す項目を絞り、ログを残し、権限を設計することまで含めた「安全な参照口」を作る、という話です。
🔷1. AIに業務システムを触らせる最初の一歩は、自動更新ではない
AI Agentを業務に入れるとき、最初から「注文を更新して」「顧客情報を登録して」「メールを送って」といった更新操作を任せるのは危険です。
理由は、失敗したときの影響が大きいからです。
- 誤った注文ステータスに更新してしまう
- 本来見せてはいけない顧客情報を返してしまう
- 権限外の部署データを検索できてしまう
- AIがどのデータを見たのか追跡できない
- 仕様を誤解したまま本番データを変更してしまう
- Prompt Injection経由で想定外の操作を呼び出してしまう
もちろん、AI Agentに業務システムを連携させる価値は大きいです。問い合わせ対応の下調べ、障害調査、商品情報確認、運用手順の参照など、効果が出やすい場面はたくさんあります。
ただし、最初の一歩は「できることを増やす」よりも「壊さない設計を作る」ほうが重要です。
そのために、まずは次のような範囲から始めるのがおすすめです。
- 仕様書を読ませる
- READMEや運用手順を読ませる
- DBスキーマを読ませる
- API一覧やログ形式を読ませる
- 注文検索や商品検索など、読み取り専用APIだけ呼ばせる
この段階で目指すのは、AI Agentが業務を勝手に動かす状態ではありません。業務システムを理解するための、安全な窓を用意することです。
🔷2. MCPのResourcesとToolsを分けて考える
MCPで業務システム連携を設計するときは、まず Resources と Tools を分けて考えると整理しやすくなります。
MCP Resources仕様では、Resourcesはサーバーがクライアントへデータを共有し、言語モデルへコンテキストを提供する仕組みとして説明されています。例として、ファイル、DBスキーマ、アプリケーション固有情報などが挙げられています。
一方、MCP Tools仕様では、Toolsは言語モデルが呼び出せる機能として説明されています。DB問い合わせ、API呼び出し、計算など、外部システムとの相互作用を可能にするものです。
ここで「MCPを使うときは、基本的にToolを呼び出すのでは?」と感じた方もいると思います。
その感覚はかなり正しいです。実際のAI Agent運用では、注文検索、ログ取得、Issue作成、DB問い合わせのように、Toolを呼び出して使う場面が多くなります。
ただし、MCPにはToolとは別にResourceという概念もあります。Resourceは、Agentが能動的に呼び出す機能というより、ホストアプリケーション側が「この情報をAIの文脈に入れる」と判断する前提情報です。つまり、Tool中心で使う実務感はありつつも、設計上は「読ませる情報」と「呼び出す操作」を分けておくと安全です。
ざっくり言うと、次のように分けられます。
Resource:
AIに読ませる前提情報。
例: 仕様書、DBスキーマ、README、ログ形式、API一覧。
イメージ: マニュアルや設計書を机の上に置く。
Tool:
AIが呼び出せる操作。
例: DB検索、API呼び出し、Issue作成、データ更新。
イメージ: 必要なときに外部システムへ問い合わせる。
この違いを曖昧にすると、「読ませるだけのつもりだったのに、実は更新できるToolも見えていた」という状態になりがちです。
🔹Resource / read-only Tool / write Toolの違い
業務システム連携では、Toolの中でもさらに read-only Tool と write Tool を分けておくと安全です。
| 種別 | 役割 | 例 | 主なリスク |
|---|---|---|---|
| Resource | AIに読ませる情報 | 仕様書、DBスキーマ、README、ログ形式 | 情報の出しすぎ、機密情報露出 |
| read-only Tool | AIが呼び出す読み取り操作 | 注文検索、商品検索、ログ検索 | 個人情報漏洩、広すぎる検索 |
| write Tool | AIが呼び出す更新操作 | 注文更新、顧客登録、メール送信 | 誤更新、外部送信、監査不能 |
Resourceは文脈です。Toolは操作です。
そしてread-only Toolは、Toolではあるものの、更新系Toolよりはリスクを抑えやすい位置づけです。ただし、「低リスク」と「無リスク」は違います。この点はあとで詳しく触れます。
業務システム連携では、Resource、read-only Tool、write Toolを分けて考えると、安全な導入順序を決めやすい。
この図のポイントは、AI Agentに渡すものを一枚岩にしないことです。
- Resource: AIに読ませる文脈
- read-only Tool: AIが呼び出せる読み取り操作
- write Tool: AIが呼び出せる更新操作
この3つを同じ箱に入れてしまうと、権限設計もレビューも雑になります。まずは「AIが何を読むのか」「何を呼べるのか」「何を更新できるのか」を分解しましょう。
🔷3. read-onlyから始める段階モデル
AI Agentの業務システム連携は、いきなり本番操作を目指さず、段階的に進めるのが現実的です。
おすすめは、Phase 0〜5で考えることです。
| 段階 | AIができること | 例 | 権限の考え方 |
|---|---|---|---|
| Phase 0 | ドキュメント参照 | 仕様書、README、運用手順 | ファイル参照のみ |
| Phase 1 | 構造参照 | DBスキーマ、API一覧、ログ形式 | 構造情報のみ |
| Phase 2 | 読み取り | 注文検索、ログ検索、商品マスタ検索 | read-only |
| Phase 3 | 提案 | SQL案、修正案、返信案 | 実行しない |
| Phase 4 | 開発環境更新 | テストデータ作成、検証DB更新 | 開発環境限定 |
| Phase 5 | 本番操作 | 人間承認つき限定操作 | 強い承認と監査 |
Phase 0〜2は、最初の安全地帯です。
この段階では、AI Agentが本番データを書き換えることはありません。まずは、業務システムの仕様、構造、読み取り結果を理解するところから始めます。
業務システム連携は、ドキュメント参照、構造参照、read-only APIから始め、書き込みや本番操作は後半で慎重に扱う。
🔹Phase 0: ドキュメント参照
最初は、仕様書やREADME、運用手順だけをAIに読ませます。
この段階では、業務システムに直接アクセスしません。AI Agentができることは、ドキュメントを読み、仕様を説明し、手順を要約することです。
たとえば、次のような情報をResourceとして渡します。
AIに読ませる情報:
- docs/order-flow.md
- docs/support-operation.md
- README.md
- API一覧
- ログ形式の説明
ここでの目的は、AIに業務の前提を理解させることです。
🔹Phase 1: 構造参照
次に、DBスキーマ、API仕様、ログ形式などの構造情報を読ませます。
ここでもまだ、実データの検索は急がなくて大丈夫です。まずは「注文テーブルには何があるのか」「問い合わせ履歴はどのAPIで取れるのか」「エラーログのtraceIdはどこに出るのか」をAIが理解できる状態にします。
🔹Phase 2: 読み取り
Phase 2で、ようやくread-only APIを呼ばせます。
たとえば、次のようなToolです。
| Tool名 | 目的 | 注意点 |
|---|---|---|
get_order_summary(orderId) |
注文概要を取得する | 明細や個人情報を返しすぎない |
search_product_master(keyword) |
商品マスタを検索する | 最大件数と検索範囲を制限する |
get_customer_support_history(customerId) |
問い合わせ履歴を参照する | 個人情報、社内メモの扱いに注意する |
get_table_schema(tableName) |
DBスキーマを参照する | 本番構成や機密カラム名の扱いに注意する |
search_error_logs(traceId) |
エラーログを検索する | トークン、パスワード、個人情報をマスクする |
ここで大切なのは、Tool名を「何でもできる検索」にしないことです。
たとえば query_database(sql) のようなToolは便利そうに見えますが、任意SQLを受け取る時点で危険です。最初は get_order_summary(orderId) のように、目的・引数・返却項目が固定されたToolにしましょう。
🔹Phase 3以降は「実行しない」「限定する」「承認する」
Phase 3では、AI Agentに修正案やSQL案を作らせても、実行は人間が判断します。
Phase 4では、開発環境や検証DBに限定して更新を試します。
Phase 5で本番操作を扱う場合も、人間承認、監査ログ、権限分離、ロールバック手順をセットにするべきです。
MCP Tools仕様でも、Tool呼び出しについては、人間が拒否できる状態を置くこと、公開しているToolをUI上で明確にすること、操作確認を提示することが推奨されています。
🔷4. read-only MCPでも安全とは限らない
ここまでread-onlyから始めることをおすすめしてきました。
ただし、ここで誤解してはいけないことがあります。
read-onlyとは「更新しない」という意味であって、「何を返しても安全」という意味ではありません。
たとえば、注文情報を読むだけでも、次のような問題は起こります。
- 顧客名、住所、電話番号、メールアドレスを返しすぎる
- 社内メモや与信情報まで返してしまう
- 全件検索に近い検索ができてしまう
- 他部署や他テナントのデータまで見えてしまう
- エラーログ内のトークンやパスワードを返してしまう
- AIが読んだ情報を、別の外部送信Toolへ渡してしまう
read-onlyは安全設計の入口です。ゴールではありません。
🔹read-only MCPで確認したいチェックリスト
最低限、次の観点は確認しておきたいところです。
| 観点 | チェック項目 |
|---|---|
| DB権限 | SELECT権限のみか |
| 任意SQL | 任意SQLを受け取らない設計か |
| 返却項目 | APIごとに返却項目を固定しているか |
| 件数制限 | 最大件数とページングを設定しているか |
| 個人情報 | 不要な個人情報を返していないか |
| ログ | 誰が何を検索したか追跡できるか |
| correlation id | 調査時にリクエストを追跡できるか |
| 部署・権限 | 他部署や権限外の情報が見えないか |
read-onlyでも、返す情報と検索範囲を絞り、ログと権限を設計しなければ安全とは言えない。
この図のように、read-only MCPでは次の4カテゴリで考えると整理しやすいです。
- DB権限:
SELECTのみにする、任意SQLを禁止する - APIレスポンス: 返却項目を固定する、ページングする
- 情報保護: 最大件数を制限する、個人情報をマスクする
- 監査と権限: ログ、correlation id、権限範囲を設計する
🔹Microsoft FoundryのMCP連携で示されている観点
Microsoft FoundryのMCP連携ドキュメントでも、MCPサーバーを追加するときは慎重にレビュー・追跡し、共有するデータを確認し、監査用にログを残すことが推奨されています。
また、ベストプラクティスとして次の観点が挙げられています。
-
allowed_toolsを使ってToolを許可リスト化する - 書き込みやリソース変更など、高リスク操作には承認を要求する
- 承認前にTool名と引数を確認する
- 承認とTool callを監査・トラブルシュート用にログへ残す
これは業務システム連携でもそのまま重要です。
「MCPサーバーをつなげば便利」ではなく、「どのToolを許可するか」「どのデータを共有するか」「誰が承認したか」を追えるようにしましょう。
🔹OWASP LLM06: Excessive Agencyとの関係
OWASP LLM06:2025 Excessive Agencyでは、LLMアプリケーションに過剰な機能、過剰な権限、過剰な自律性を与えることがリスクとして整理されています。
特に業務システム連携では、次の例が刺さります。
- 読み取り目的の拡張なのに、DB接続ユーザーが
UPDATE、INSERT、DELETE権限まで持っている - ユーザーごとの権限ではなく、広すぎる共有アカウントで下流システムへアクセスしている
- 高影響な操作なのに、人間の確認なしで実行できる
つまり、read-onlyから始めることは、AI AgentのExcessive Agencyを抑える現実的な第一歩です。
🔷5. C# / ASP.NET Coreでread-only連携を作るなら
ここからは、C# / ASP.NET Coreでread-only連携を作る場合の考え方を見ていきます。
前提として、記事用に簡略化したサンプルです。実システムでは、認証、認可、例外処理、監査ログ、テナント分離、個人情報マスキングを追加してください。
🔹設計方針
read-only APIを作るときは、次の方針に寄せます。
- ASP.NET Core Minimal APIで読み取り専用エンドポイントを作る
- DB接続ユーザーは
SELECT権限のみ付与する - 任意SQLを受け取るAPIは作らない
- APIごとに返却項目を固定する
- ページングを必須にする
- 最大件数を制限する
- ログとcorrelation idを残す
- 個人情報や秘密情報をマスクする
- 本番DB接続は最後に検討する
🔹読み取り専用エンドポイント例
注文IDを指定して、注文概要だけを返すAPIです。
app.MapGet("/orders/{orderId}/summary", async (
string orderId,
OrderReadDb db,
ILogger<Program> logger,
CancellationToken cancellationToken) =>
{
logger.LogInformation("注文概要が要求されました。OrderId={OrderId}", orderId);
var order = await db.Orders
.AsNoTracking()
.Where(x => x.OrderId == orderId)
.Select(x => new OrderSummaryResponse(
x.OrderId,
x.Status,
x.OrderedAt,
x.TotalAmount))
.SingleOrDefaultAsync(cancellationToken);
return order is null ? Results.NotFound() : Results.Ok(order);
});
public sealed record OrderSummaryResponse(
string OrderId,
string Status,
DateTimeOffset OrderedAt,
decimal TotalAmount);
ポイントは、返却項目を OrderSummaryResponse に固定していることです。
顧客名、住所、電話番号、メールアドレス、社内メモなどが不要なら返しません。AI Agentが便利に使えることよりも、返す情報を必要最小限にすることを優先します。
また、Entity Framework Coreを使うなら、読み取り用途では AsNoTracking() を使うと「更新前提ではない」意図がコード上にも出ます。
🔹ページング付き検索例
商品マスタ検索のような一覧系APIでは、ページングと最大件数制限を入れます。
app.MapGet("/products/search", async (
string keyword,
int page,
int pageSize,
ProductReadDb db,
CancellationToken cancellationToken) =>
{
page = Math.Max(page, 1);
pageSize = Math.Clamp(pageSize, 1, 50);
var products = await db.Products
.AsNoTracking()
.Where(x => x.Name.Contains(keyword))
.OrderBy(x => x.ProductCode)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new ProductSearchItem(
x.ProductCode,
x.Name,
x.IsActive))
.ToListAsync(cancellationToken);
return Results.Ok(products);
});
public sealed record ProductSearchItem(
string ProductCode,
string Name,
bool IsActive);
ここでは pageSize を最大50件に制限しています。
AI Agentは、必要なら何度も検索できます。だからこそ、1回の検索で返す件数は絞りましょう。全件取得に近いAPIを作ると、read-onlyでも情報漏洩リスクが跳ね上がります。
🔹任意SQLを受け取るAPIは避ける
以下のようなAPIは作らないほうが安全です。
app.MapPost("/query", async (string sql, DbConnection connection) =>
{
// 任意SQLを実行できてしまうため危険
return await connection.QueryAsync(sql);
});
このAPIには、次の問題があります。
-
SELECTだけでなくUPDATE、DELETEが実行される可能性がある - 対象テーブルを制限しにくい
- 返却項目を固定できない
- 最大件数やページングを強制しにくい
- AIが生成したSQLをそのまま実行する流れになりやすい
- 監査や承認の設計が曖昧になる
どうしても柔軟な検索が必要な場合でも、最初は目的別のAPIを作るほうが安全です。
よい方向:
get_order_summary(orderId)
search_product_master(keyword, page, pageSize)
search_error_logs(traceId)
避けたい方向:
query_database(sql)
execute_command(command)
call_any_api(url, body)
AI Agent向けのToolは、便利すぎるほど危険になることがあります。
💡Tips: read-only Toolの名前は「できること」を狭く書く
Tool名は、AI Agentへの仕様書でもあります。
たとえば、次のように名前を付けると、目的が狭くなります。
get_order_summary:
注文の概要だけを取得する。
search_product_master:
商品マスタを検索する。
search_error_logs:
traceIdに紐づくエラーログを検索する。
逆に、次のような名前は範囲が広すぎます。
query:
何を検索するのか分からない。
execute:
何を実行するのか分からない。
manage_order:
読み取りなのか更新なのか分からない。
Tool名、説明、引数、返却項目を見ただけで「このToolは何をして、何をしないのか」が分かる状態にしておくと、レビューもしやすくなります。
❓困ったときは: まず権限とログを見る
read-only連携を作っていて不安になったら、まず次の2つを見直してください。
▸DBユーザーが本当にread-onlyか
アプリケーション側で「更新APIを作っていない」だけでは足りません。
DB接続ユーザー自体に SELECT 以外の権限が付いていないか確認しましょう。OWASP LLM06でも、読み取り目的なのに更新・挿入・削除権限まで持っている設計は、過剰な権限の例として扱われています。
▸誰が何を検索したか追えるか
read-onlyでも、監査ログは必要です。
最低限、次の情報は追えるようにしておきたいです。
- 呼び出したユーザー
- 呼び出したTool名
- 引数
- 返却件数
- correlation id
- 実行時刻
- 承認が必要な操作なら承認者
「更新していないからログ不要」ではなく、「読んだ情報が機密かもしれないからログが必要」と考えましょう。
✅まとめ: 業務システム連携は「できる」より「壊さない」が先
AI Agentを業務システムにつなぐと、できることは一気に増えます。
ただし、最初に渡すべきなのは更新権限ではありません。
この記事では、次の考え方を紹介しました。
- AIに業務システムを触らせるなら、まずread-onlyから始める
- MCPではResourceとToolを分けて考える
- Toolの中でもread-only Toolとwrite Toolを分ける
- Phase 0〜2で、ドキュメント参照、構造参照、読み取りAPIを整える
- read-onlyでも、個人情報、検索範囲、返却項目、ログ、権限は設計する
- C# / ASP.NET Coreでは、任意SQLを避け、目的別APIと固定レスポンスにする
- 書き込みや本番操作は、人間承認と監査を前提に最後に考える
業務システム連携では、「AIに何ができるか」だけを見ると危険です。
最初に考えるべきなのは、AIが何を読めるのか、何を呼べるのか、何を絶対にできないのかです。
AIに業務システムを触らせるなら、まず“読めるだけ”から始めましょう。
🔷参考URL
- MCP Resources specification
- MCP Tools specification
- MCP Security Best Practices
- Connect agents to Model Context Protocol servers - Microsoft Foundry
- OWASP LLM06:2025 Excessive Agency
※お役に立てたらストック、いいねをよろしくお願いします!!


