ERPのためのMCPを構築するには、4つの決定が必要です。テーブルではなく取引を公開します:ツールは、請求書を作成したり、支払いを記録したりするなど、システム内で人が行えることにすべきです。その中にビジネスルールを含めます。リストを読むモデルのために各ツールに名前を付け、説明し、説明の中で守るべき制約を設定し、決して見ることのない文書には記載しません。各リクエストのOAuth IDが、どのツールがリストされるか、各呼び出しが実行されるかを決定します。そして、リトライ、拒否、質問が安全になるようにすべての書き込みを設計します。モデルはこれらすべてを生成します。
輸送、発見、サインインは指定されており、任意のSDKがそれらを処理します。サーバーの価値はその4つの決定にあり、それを正しく行うビジネスシステムは、Claude、ChatGPT、または他のクライアントが何も知らなくても操作可能です。
取引から始め、テーブルではない
ERPを公開する際の最初の本能は、各テーブルごとに作成、読み取り、更新、削除のツールを生成することです。それは大きく均一なリストを生成し、モデルはそれをうまく処理できません。請求書には各行に税率が必要であるというビジネスルールや、在庫は予約される前に出荷できないというルールは、モデルが見ることのできない場所に存在します。代わりにアクションを公開します。役立つテストは、人がそのツールを今日行ったこととして説明できるかどうかです:請求書を発行した、支払いを記録した、取引を移動した、追跡をスヌーズした。それぞれがそのルールを持ち、入力を検証し、読みやすい結果を返します。
アクションに加えて、モデルが行動する前に尋ねる質問に答える少数の要約ツールを追加します。アカウントのプロファイル、健康状態、未処理項目、最近の履歴を返す1回の呼び出しは、モデルに4回の呼び出しと数千トークンのコンテキストを節約し、次のアクションをより良く情報提供します。Soisはこれらをエグザミナーツールと呼びます; 連絡先を確認する および 会計概要を取得する 二つあります。全体の表面も考慮してください:Claude Codeはデフォルトでサーバーの出力を呼び出しごとに制限し、ClaudeとOpenAIの両方が大規模なリストのために遅延読み込みまたはツール検索を提供します。そのため、数百のツールを持つサーバーは、クライアントがキャッシュできるように仕様で求められているため、決定論的な順序で返す必要があり、リスト表示の前に役割でフィルタリングする必要があります。
モデルが正しいものを選べるようにツールに名前を付ける
仕様は名前を軽く制約します:1から128文字、文字、数字、アンダースコア、ハイフン、ドット、ケースセンシティブ、サーバー内で一意です。それ以外はすべて慣習であり、機能する慣習は動詞の後にビジネス名詞を一貫したケースで続け、同じ動詞がどこでも同じ意味を持つことです。モデルは選択する際に 請求書を検索, 請求書を取得する および 請求書を作成する リスト、1つのレコード、書き込みの間で選択しており、そのパターンをサーバー全体で一度学習します。
| 弱い | より良い | なぜ |
|---|---|---|
請求書 | 請求書を作成する | 名詞だけでは読み取りか書き込みかはわかりません;クライアントはそれに注釈を付けることができず、モデルはそれを兄弟と比較してランク付けすることができません。 |
請求書作成V2最終 | 請求書を作成する | バージョンとステータスはサーバーに属し、名前には含まれません。変更される名前はキャッシュされたツールリストやプロンプトキャッシュを壊します。 |
会計処理を行う | 支払いを記録, 請求書リマインダーを送信 | モード引数を持つキャッチオールは取引を隠します。取引ごとに1つの名前を使用することで、クライアントはツールごとに確認を適用できます。 |
請求書を取得 および 連絡先を取得 混合 | 一貫したケース | クライアントはサーバーによって名前をプレフィックス化します。サーバー内の一貫性はモデルが依存するものです。 |
説明には、ツールを使用するタイミング、使用しないタイミング、モデルが呼び出す前に遵守すべきルールが含まれます。
説明は、行動を求められるモデルによって読み取られるため、指示として書いてください。最初の文でツールの機能を述べ、その後に条件を示します。近くのリクエストに対して兄弟ツールが適切な選択である場合は、その名前を挙げてください。結果が正確であるためにフィールドを設定する必要がある場合は、必要に応じて大文字で示してください。Soisの請求書ツールは、税率が各行に設定される必要があり、正確な税率がどこから来るかをモデルに伝えます。 , 請求書ツールの説明によれば、税率は各行に設定する必要があり、ワークスペースの正確な税率はそのコールから取得されます。モデルは説明を読み、良い説明はVATなしで請求書が送信されるのを防ぎます。請求書は1行、数量12、顧客の条件に基づく税率で作成され、新しい請求書の識別子と番号が結果として受け取られました。それを, because an invoice with no VAT is a worse failure than a refused call. Include one example call. Everything the model needs to call the tool correctly should be in the tool, because it will never open your documentation.
ツール定義の例
これは、クライアントが受け取るSoisの請求書ツールです。 tools/list重要なフィールドに絞り、注釈と出力スキーマを現在の仕様に従って追加します。これは、動詞-名詞の名前、指示的な説明、モデルのエラー防止を行うプロパティの説明を持つスキーマ、そしてクライアントが確認するかどうかを決定するために使用できるヒントを示すパターンです。
{
"name": "createInvoice",
"title": "Create invoice",
"description": "Create a new invoice of any type and return the draft with its auto-generated number. TAX: set tax_rate on each line (for example 20 for 20% VAT); call listTaxTypes for this workspace's exact rates. If the user says 'plus VAT' you MUST set tax_rate or the invoice goes out with no VAT. To email the result use sendInvoice. Example: createInvoice({ type: \"sales_invoice\", contact_id: \"uuid\", currency: \"GBP\", lines: [{ description: \"Consulting\", quantity: 10, unit_price: 150 }] })",
"inputSchema": {
"type": "object",
"properties": {
"type": { "type": "string", "description": "sales_invoice, purchase_invoice, sales_credit_note or purchase_credit_note" },
"contact_id": { "type": "string", "description": "Contact UUID (bill-to for sales, bill-from for purchases)" },
"currency": { "type": "string", "description": "ISO code, for example GBP. Uses the workspace default if omitted" },
"invoice_date": { "type": "string", "description": "ISO date. Defaults to today" },
"reference": { "type": "string" },
"lines": {
"type": "array",
"description": "Line items. Every line MUST carry the numeric unit_price the user asked for",
"items": {
"type": "object",
"properties": {
"description": { "type": "string" },
"quantity": { "type": "number", "description": "Defaults to 1" },
"unit_price": { "type": "number", "description": "NUMBER only: no currency symbols, no thousands separators. Use the exact amount stated; never guess or round" },
"tax_rate": { "type": "number" },
"discount_percent": { "type": "number" }
},
"required": ["description", "unit_price"]
}
}
},
"required": ["type"]
},
"outputSchema": {
"type": "object",
"properties": {
"invoice_id": { "type": "string" },
"number": { "type": "string" },
"status": { "type": "string" },
"total": { "type": "number" }
},
"required": ["invoice_id", "number", "status"]
},
"annotations": {
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false
}
}注釈は次のように述べています:これは書き込み、ドラフトを追加するだけであり、2回呼び出すと2つのドラフトが作成され、システム外のものには触れません。クライアントは、サーバーが信頼できない限り、注釈を信頼できないものとして扱う必要があります。したがって、これらは確認動作のためのヒントであり、サーバー自身のチェックの代わりにはなりません。
その定義における3つの選択は意図的です。結果は、モデルが持ち込む必要のある識別子を返します。 , PDFを添付してメール送信するために渡され、最後に および 支払いを記録, which is the specification's recommended way to relate calls now that servers hold no session state. The tool creates a draft, not a posted invoice, so the write is additive and a person or a separate approval tool finalises it. And the output schema means an integration can read the number and total as data while the model reads the same result as text.
ユーザーに合わせたツールの範囲設定
HTTP経由で呼び出し元は、あなたのサーバーにバインドされたOAuthアクセストークンを持って到着し、そのトークンが個人を特定します。仕様は結果を許可します tools/list リクエストの資格情報によって異なるため、最初のスコーピング決定は、その人の役割によってリストをフィルタリングしてから返すことです:倉庫ユーザーは受け取りません 請求書を承認するリストは接続ごとに変わったり、他の呼び出しの副作用として変わったりしてはいけません。認証によってのみ変わるため、キャッシュ可能です。
2つ目の決定は、実行時に再度確認することです。クライアントは任意の呼び出しを送信でき、モデルはツールの結果のテキストによって操作されて試行されることがあります。すべての呼び出しでトークンからユーザーを解決し、ツールが要求する権限を確認し、モデルが読み取れるツール実行エラーで拒否します。OAuthスコープは粗く保ち(Soisは読み取り、書き込み、オフラインスコープを発行します)、ERPの独自の役割を細かい境界にします。これらの役割はすでに存在し、維持されており、ビジネスにとって意味を持っています。すべての呼び出しをその引数と結果を持つ人物にログに記録し、エージェントの作業が個人の作業と同様にレビュー可能であるようにします。
- トークンが届きました署名を検証し、対象がこのサーバーであることを確認します。RFC 8707に従い、それ以外は401で拒否します。
- 本人を確認するトークンをワークスペース内のユーザーにマッピングし、その役割とインストールされたアプリを読み込みます。
- リストをフィルタリングします。その役割が使用できるツールのみを、ツール/リストから安定した順序で返します。
- コールを確認します。ツール/コールで、再度権限を確認し、欠如している場合はisErrorで拒否します。何も実行されません。
- 実行してログに記録します。トランザクションを実行し、自分のエージェントが推論を行った場合はメーターを計測し、その人の監査ログにコールを書き込みます。
書き込みの処理
あいまいな結果を受け取ったモデルは再度呼び出し、エラーを受け取ったモデルは修正された入力を試みます。それに合わせて設計してください。作成する書き込みはハンドルを返し、可能な場合は冪等性キーまたは自然キーを受け入れて、再試行を検出できるようにする必要があります。状態を変更する書き込みは、実行する遷移について明示的であり、不可能なものは読みやすい理由で拒否する必要があります:無効な請求書に対する支払いを記録することは isError その旨を示す結果であり、静かな無操作やスタックトレースではありません。部分的な書き込みを残さないでください。マルチステップツールが完了できない場合は、ロールバックして報告します。
- ドラフトと承認を優先します。 作成を追加的(ドラフト)にし、最終化には独自のツールと権限を与え、破壊的なステップはクライアントが確認し、役割が制御するものにします。
- 破壊的なツールにマークを付けます。 設定
destructiveHint無効や削除については説明に明記してください。ClaudeとChatGPTは、呼び出し前に確認するかどうかを決定する際にそのような信号を使用します。 - 推測せずに尋ねてください。 ツールが決定できない場合は、入力が必要な結果を返し、質問を人に投げかけて、回答を得た後に再度呼び出してください。
- 影響範囲を制限してください。 接続ごとにレート制限を設け、独自のエージェントが推論を行う統合ごとに支出を制限し、スキーマに関係なくすべての入力をサーバー側で検証してください。スキーマはモデルへのアドバイスであり、強制ではありません。
実際のクライアントで表面をテストする
MCPインスペクターは行動します。 tools/list および tools/call OAuthフローを進めます。本当のテストはモデルです。Claudeをカスタムコネクタとして接続するか、開発者モードのChatGPTにサインインし、狭い役割を持つユーザーとしてサインインして、3つまたは4つのツールを必要とする1つのルーチン結果を求めてください。どのツールを選択するか、なぜ選択するかを観察してください。誤った選択はほとんど常に説明の問題です。その後、権限のないユーザーとしてサインインし、モデルが繰り返す理由で正しい呼び出しで実行が停止することを確認してください。
これがSoisワークスペースサーバーの構築とチェックの方法です:ツールとしてのトランザクション、指示的な説明、役割でフィルタリングされたリスト、すべての呼び出しに対する二重チェック、承認前のドラフト、そして人が読めるログ。マーケットプレイス向けにアプリを構築する開発者は、同じルールの下で同じリストにツールを公開するため、アプリはインストールされた瞬間に任意のエージェントによって操作可能になります。このパターンは特定の製品に限定されず、それを採用するERPはエージェントが実行できるものになります。
人々が尋ねる質問
ERP MCPサーバーはどれだけのツールを公開すべきですか?
自動化する価値のあるトランザクションの数だけ、ユーザーごとにフィルタリングされて各呼び出し元が作業セットを見られるようにしてください。完全なシステムでは数百が一般的です。重要なのは、リストが安定していて、役割でフィルタリングされ、一貫した動詞で整理されていることです。そうすればモデルは候補をランク付けできます。
細かい権限のためにOAuthスコープを使用すべきですか?
接続には粗いスコープを使用し、細かい境界にはERPの独自の役割を使用し、すべての呼び出しで確認します。役割はすでに存在し、ビジネスによって維持されています。並行するスコープの仕組みはそれらから逸脱します。
モデルが2回呼び出した場合、書き込みはどのように振る舞うべきですか?
冪等性または自然キーを通じて繰り返しを検出し、既存のレコードを返すか、書き込みを加算的にし、重複が明確に表示されるように報告します。静かに失敗せず、部分的な書き込みを残さないでください。
ツールの注釈はクライアントによって強制されますか?
いいえ。これらはヒントであり、仕様はクライアントに対してサーバーが信頼できない限り、信頼できないものとして扱うように指示しています。クライアントはこれらを使用して確認の振る舞いを選択します。サーバー自身の権限と検証チェックが危害を防ぎます。
- モデルコンテキストプロトコル仕様(2026-07-28):ツール ツール名、スキーマ、注釈、構造化結果、エラーハンドリングおよび状態を持つハンドルのガイダンス
- モデルコンテキストプロトコル仕様:認可 トークンオーディエンスの検証、スコープの課題およびリクエストごとの認可モデル
- OpenAIアプリSDK:MCPサーバーを構築する ChatGPTが確認の振る舞いのためにreadOnlyHint、destructiveHintおよびopenWorldHintをどのように使用するか
- Soisドキュメント:ワークスペースMCPサーバー ツールの参照、役割フィルタリング、制限およびエラーコード
この文書は、記載されている製品が変更される際にレビューされます。次回の予定レビュー: 2026年12月4日.
