2026年6月8日、Anthropic は Claude のディレクトリにあるコネクタの所有者にダッシュボードを提供しました。アクティブユーザー数、ツール呼び出しの総数、ディレクトリ内の順位が表示されます。さらに「ヘルススコア、エラー率、レイテンシーをひと目で確認でき、ツールごとのエラー内訳で何が失敗しているかを特定できる」ようになっています。
その 1 年前、Weights & Biases の Alex Volkov は同じ問題を反対側から説明していました。彼のエージェントが MCP 経由でツールを呼び出すようになると、「自分のコードを最初から最後まで実行していたときに慣れ親しんでいたオブザーバビリティが、少し見えなくなってしまった」のです。共同講演者である Dylibso の Benjamin Eckel は、その理由を示しました。リモートの MCP サーバーは呼び出し側の管理外で動くため、「トレース上では 1 つのサービススパンとして現れる」のです。
どちらの視点もサーバーの外側にあります。クライアントに見えるのは中身の見えない 1 つのスパンです。ディレクトリに見えるのは合計値です。サーバーが何を求められ、何を拒否し、何に触れたのかは、どちらにも見えていません。それを見たのはサーバーだけなので、記録できるのもサーバーだけです。
ここで紹介するのは、Tajo の MCP サーバーが記録している内容です。それを動かしているコードから読み取り、ドキュメントにも記載しています。プロトコルについては MCP サーバーとは何か で説明しています。この記事で扱うのは、ログの 1 行です。
呼び出し 1 件につき 1 行
ダッシュボードは港長の視点です。入港した船、出港した船、遅れた船がわかります。リクエストログは船自身の航海日誌で、その時その場で船上で書かれます。
Tajo のワークスペースサーバーとすべてのコネクタサーバーでは、tools/call は必ず 1 行で終わります。行は、応答の内容にかかわらず、応答が組み立てられた後に書かれます。キーに書き込み権限がない、あるいはエンドポイントが読み取り専用であるという理由で拒否された呼び出しも、ほかの呼び出しと同じように 1 行になります。存在しないツールへの呼び出しも同様です。
行が保持するもの、そして保持を拒むものは次のとおりです。
| フィールド | 保持するもの | 保持しないもの |
|---|---|---|
| 誰が | 呼び出した API キーの ID。OAuth サインインで得たトークンもキーとして扱います。 | キーの秘密の値やそのプレフィックス。 |
| どこで | ワークスペースサーバーまたはコネクタサーバーと、そのコネクタおよびプロファイル。 | |
| ツール | サーバーにその名前のツールがある場合の名前。 | クライアントが送るそれ以外の名前。(unknown) として保存されます。 |
| 効果 | read、write、send、destructive のいずれか。その呼び出しが持ちうる最も重い効果です。 | |
| 結果 | ok、または unknown_tool のような短い snake_case のエラーコード。 | エラーの説明文。コードでないものはすべて tool_error として保存されます。 |
| 所要時間とサイズ | 到着から応答までのミリ秒数と、呼び出し側が受け取ったバイト数。 | |
| トレース ID | x-request-id、x-trace-id、または W3C の traceparent ヘッダーから得たリクエストの ID。なければ新しく発行します。 | 16 進数でも UUID でもないヘッダー値。 |
| レコード | 呼び出しが指定または生成したレコードの ID を最大 20 件。コンタクト、メッセージ、承認などです。 | レコードそのもの。 |
| 本文 | 引数と応答。スクラブ済みで、それぞれ最大 4 KB。 | 秘密情報、自由記述、そして後述の個人データ。 |
このうち 3 つの拒否は、データではなくクライアントに関するものです。ツール名、エラーコード、トレース ID はいずれも外部から届きます。それぞれ、サーバーが保証できる形でのみ保持されます。呼び出し側が送ってきたものを何でも保存するログには、ツール名の列に顧客のメールアドレスが入るなど、何でも詰め込めてしまいます。
講演の最後に Benjamin Eckel が投げかけた未解決の問いは、コレクターがどうやって「それがエラーを含む MCP のツール呼び出しだと」知るのか、というものでした。1 台のサーバーの中であれば、答えは 1 つの列です。ok が false になり、どのエラーかはコードが示します。
引数:撤回したルール
反論はもっともで、私たち自身のものでもあります。引数をログに残せば、顧客データの 2 つ目のコピーを、どの削除リクエストも届かない場所に作ることになります。2026年10月18日までは、それが私たち自身のルールでした。どちらも個人データを含みうるため、ログには引数も結果の本文も残していませんでした。
それは誤ったトレードオフでした。何が送られ、何が返ってきたのかを示せないリクエストログは、それが存在する唯一の理由である問い、つまり「エージェントの呼び出しはなぜ失敗したのか」に答えられません。
そこで本文を保持することにし、これまで保持しなかった理由には別の方法で対処しました。各本文は、キューに入る前に決定論的な 1 回の処理を通ります。
- 秘密情報は残りません。 名前が token、password、secret、signature、cookie、session、またはそれに類する 20 語ほどの単語を示すフィールドには、
[secret]だけが残ります。既知の認証情報の形をした値も、どこに現れても同じです。これには bearer トークン、JWT、秘密鍵、パスワードを含む URL、そして 40 文字以上続く不透明なキー文字の並びが含まれます。 - 文章はまったく保持しません。
html、text、body、markdown、contentという名前のフィールドには[redacted]だけが残ります。文章には、どのパターンでも見つけられない氏名や住所が含まれるからです。 - 個人データは恒久的にマスクされます。 メールアドレス、電話番号、氏名、住所、メモなど、名前が個人データを示すフィールドには
[redacted]だけが残ります。それ以外の文字列の中にあるメールアドレス、電話番号、カード番号、IBAN はマスクされます。 - 本文は小さく保たれます。 文字列は 512 文字、リストは 20 項目、オブジェクトは 50 キー、ネストは 6 階層で切り詰められます。本文全体は 4 KB で切り詰められ、切り詰めた印が付きます。
保持する内容がさらに少ない呼び出しが 2 種類あります。利用者のチャットが別のアプリから持ち込んだコンタクトは、本文ではなく、目印と件数としてだけ記録されます。ログを読み取る呼び出しは応答を保持しません。その応答はほかのログ行にすぎないからです。
次にコストです。マスクは恒久的なもので、誰かが鍵を持つ暗号化ではありません。ログでは、バウンスしたメールアドレスを見ることはできません。見えるのはコンタクトの ID で、コンタクト自体はそれ自身のルールのもとで、呼び出し 1 回で取得できます。ログはワークスペースの消去処理の対象外にあるため、マスクをその処理まで待たせることはできません。
ログが監査証跡ではない理由
Tajo にはすでに追記専用の監査ログがあります。各行は直前の行のハッシュを持つため、どこかを編集するとチェーンが壊れます。では、なぜツール呼び出しをそこに書かないのでしょうか。
チェーンにはコストがあるからです。追記のたびにワークスペース単位のロックを取り、チェーンを延ばすために直前の行を読みます。すべての読み取りをそこに通すと、ワークスペースの呼び出しが 1 つのロックの後ろに並ぶことになります。さらに、監査ログが示すために存在する状態変更が、何千もの読み取りの下に埋もれてしまいます。
そのため、2 つの記録は問いによって役割を分けています。リクエストログは、エージェントが何を求め、何が起きたかを 30日間示します。監査ログは、何が変わり、誰がそれを許可し、その後に誰かが記録を編集したかどうかを示します。
承認は監査ログの側にあります。Tajo のコネクタプロファイルでは、propose ツールが宣言されたアクションを準備し、承認されると apply ツールがそれを実行します。提案が承認されるまで、プロバイダーには何も届きません。承認するのは人か、ワークスペースが有効にしたルールです。propose の呼び出しの行は、作成した承認をレコードの 1 つとして記録します。承認そのものは、正確な入力の SHA-256 ダイジェストに結び付けられています。承認は、あなたが見たとおりの入力だけを対象にします。フィールドを 1 つでも変えれば、もう一致しません。書き込みが反映されると、その監査行には入力のダイジェストとプロバイダーの応答のダイジェストが残り、応答の値そのものは残りません。
1 行のコスト
1 行はデータベースへの書き込みであり、書き込みにはコミットが伴います。2026年10月8日までは、各呼び出しが応答の前に自分のコミットを待っていました。私たちのホストでは約 2.6 ms です。1 つのクライアントにとって、それは小さなツール呼び出しの 4 分の 1 にあたりました。
現在は、呼び出しが終わった時点で行を組み立て、キューに入れます。フラッシュ処理が 最大 100 ms 後にキューを書き込みます。ワークスペースごとに 1 トランザクションなので、多くの呼び出しが 1 回のコミットを共有します。タイムスタンプを含め、行の内容は何も変わりません。5,000 行が待機している場合、次の呼び出しは行を捨てるのではなく、フラッシュを待ちます。
記録が原因で呼び出しが失敗することはありません。書き込みに失敗すると 1 行ずつ再試行し、それでも失敗した行はログに記録したうえで破棄します。プロセスが強制終了されたときに失われるのは、キューに残っていたものです。つまり、最大で直近 100 ms 分の呼び出しです。
読み返す
logs.list は、ワークスペースの呼び出しを新しい順に、本文なしで返します。時間、結果または HTTP ステータス、ソース(MCP、または同じテーブルを共有する REST API)、API キーで絞り込めます。既定では 1 ページ 50 件で、最大 100 件です。logs.get は、キーの現在の名前、ステータス、所要時間、スクラブ済みのリクエストと応答、触れたレコードとともに 1 件の呼び出しを返します。
どちらも呼び出し側のワークスペースだけを読み取ります。別のワークスペースの行 ID は見つかりません。
ツールエラーにはリクエスト ID が含まれます。その ID をサーバーが発行した場合、あるいは 16 進数か UUID として届いた場合、それが行のトレース ID になります。エラーを受け取ったエージェントは、その呼び出しを特定する 1 つの値を人に渡せます。
作られているもの、作られていないもの
本稿執筆時点で作られているもの:
- ワークスペースサーバーとすべてのコネクタサーバーで、拒否された呼び出しや不明な呼び出しを含め、
tools/call1 件につき 1 行。 - キー ID、サーバー、コネクタ、プロファイル、ツール、効果、結果、所要時間、結果のサイズ、トレース ID、触れたレコード最大 20 件。
- スクラブ済みの引数と応答。それぞれ最大 4 KB。
- ワークスペースに限定され、30日間保持される
logs.listとlogs.get。 - 入力ダイジェストに結び付けられた承認と、ハッシュチェーン型の監査ログに入力と出力のダイジェストとともに記録される、実行済みの書き込み。
作られていないもの。頼る前に知っておく価値があります:
- ヘルススコアも、ツールごとのグラフも、エラー率の上昇に対するアラートもありません。呼び出し数、エラー数、最も遅い所要時間のツールごとの集計は Tajo の運用担当者向けには存在しますが、あなたが開ける画面にはありません。
logs.listはツール名やトレース ID で絞り込めません。リクエスト ID に対応する行を探すには、時間とキーで絞り込んでください。- 行は、あなたが運用するトレーシングシステムにはエクスポートされません。トレース ID は HTTP ヘッダーからのみ読み取られ、講演でトレースコンテキストを運ぶために使われていた MCP の
_metaフィールドからは読み取りません。 - 30日が経つと行は削除されます。アーカイブやエクスポートはありません。
- マスクされたものは、ログから復元できません。
- 強制終了により、直近 100 ms 分の行が失われる可能性があります。
講演は、MCP におけるオブザーバビリティは「均等に行き渡っていない」という言葉で締めくくられました。下流のダッシュボードではそれを解決できませんし、サーバーの入口で途切れるトレースでも解決できません。失敗した同期には独自の記録が必要です。何かを求めたすべての呼び出しも同じです。
呼び出しを見たのはサーバーです。ほかには誰も見ていません。だから、そこで記録してください。
よくある質問
MCP サーバーはツール呼び出しごとに何をログに残すべきですか?
サーバーが書く、呼び出し 1 件につき 1 行です。どの API キーが呼び出したか、どのサーバーとコネクタか、ツールが存在する場合はそのツール名、効果クラス、ok または短いエラーコード、所要時間、結果のサイズ、リクエストのトレース ID、呼び出しが指定または生成したレコードの ID、そして秘密情報と個人データを取り除いた引数と応答です。Tajo の MCP サーバーは、拒否された呼び出しも含めてすべての tools/call についてこの行を書き、30日間保持します。
MCP のリクエストログにツールの引数を残すべきですか?
はい、スクラブしたうえで残します。引数のないログでは、呼び出しが失敗した理由を説明できません。Tajo は2026年10月18日まで本文を一切保持していませんでしたが、現在は決定論的な 1 回の処理を通したうえで両方を保持しています。秘密情報は [secret] に、自由記述と個人データのフィールドは [redacted] になり、メールアドレス、電話番号、カード番号、IBAN はマスクされ、各本文は 4 KB で切り詰められます。マスクは元に戻せないため、ログはレコードをコピーせず、ID でレコードを指し示します。
MCP のツール呼び出しログを監査ログと分けておくのはなぜですか?
答える問いもコストも違うからです。Tajo の監査ログは状態変更のハッシュチェーンで、追記のたびにチェーンを延ばすためにワークスペース単位のロックを取ります。すべての読み取りをそこに通すと、ワークスペースの呼び出しがそのロックの後ろに並び、変更が読み取りの中に埋もれてしまいます。ツール呼び出しは 30日間保持される、チェーンのない別のテーブルに入ります。呼び出しが準備した書き込みは、引き続きそれぞれ独自の監査行を残します。