本文へスキップ
mcpd
デーモンなし
ソース

コスト集計

コストの値は、どこから来たかを言えて初めて意味があります。ここにあるのは、トークン数から画面上の数字までの、すべての段です。

値付けは取り込み時に一度だけ

モデル id とトークン数を持つスパンが届くと、mcpd はそのモデルを価格表で 引き、その呼び出しの費用を計算して、結果をスパンに保存します。読み出しの ときに計算し直すものは、何もありません。

これが、このページで重要な決定です。価格は変わります。もしコストを、 クエリの時点で、その日たまたま読み込まれていた価格表から導いていたら、 来月の値下げが先月のコストを黙って書き換え、あなたが誰かに報告した数字は、 その人が確かめに行ったときにはもう無い、ということになります。取り込み時に 値付けすることで、その値は、呼び出しの時点で正しかった単価に対して固定 されます。保存されたコストは、それを生んだ価格表の id も記録するので、値 からその裏にある単価までたどれます。

すでにコストを持って届いたスパンは、届いたそのままにされます。プロバイダー が実際の金額を返し、それをあなたが記録したなら、mcpd はあなたの値を残し、 その上から値付けし直すことはしません。is_estimated フラグが、 この 2 つを分けます。mcpd が価格表から導いたものは推定として印が付きます。 実際に推定だからです。

単価は 100 万トークンあたり

価格表の単価はどれも、100 万トークンあたりの通貨単位です。どのプロバイダーも その形で公表しています。価格ページから写した単価は、そのまま価格表に入り ます。午前 3 時に割り算を間違える余地はありません。1 つの計測項目の計算は tokens × rate ÷ 1,000,000 です。

コストは実行ではなく、ステップに載ります

モデル呼び出しは、それぞれ自分の値を持ちます。実行の合計はスパンの和で あり、mcpd はカウンターを足していくのではなく、スパンが 1 つ届くたびに、 スパンから合計を計算し直します。スパンは順序が入れ替わって届き、リトライされ、 その場で更新されます。足していく合計は、この 3 つのどれでもずれます。下に 並ぶ行と一致しない見出しの数字は、そのページの他のすべての数字への信頼を 壊します。

Trace b3d9e71a Fault
0ms 2.1s 4.2s 6.3s 8.4s
  1. agent support_agent fail
  2. model chat
  3. tool returns_policy
  4. model chat
  5. tool returns_policy
  6. model chat
  7. tool returns_policy

The model called one tool three times and never answered. That is visible in four seconds here, and invisible in a log file.

上の 3 つのモデル呼び出しは、$0.00015、$0.00018、$0.00021 と値付けされて います。ヘッダーにある実行の合計は、それらの和であって、それ以外は含み ません。ツール呼び出し、メモリーの参照、ガードレールはトークンを消費して いないので、コストを持たず、合計にも寄与しません。

計測項目

モデル呼び出しは、1 つのトークン数ではありません。プロバイダーは複数の 計測項目をそれぞれ違う単価で課金し、価格表は、その 1 つずつに単価を与えます。

単価対象価格表にない場合
input 通常の入力トークン。 必須です。
output 通常の生成トークン。 必須です。
cache_read プロンプトキャッシュから返されたトークン。 input で課金します。
cache_write プロンプトキャッシュに書き込まれたトークン。 input で課金します。
cache_write_5m 5 分キャッシュへの書き込み。プロバイダーが TTL ごとに値付けする場合です。 cache_write、次いで input にフォールバックします。
cache_write_1h 1 時間キャッシュへの書き込み。 cache_write、次いで input にフォールバックします。
audio_input 音声の入力トークン。 input で課金します。
audio_output 音声の出力トークン。 output で課金します。
reasoning 隠れた推論トークン。プロバイダーがこれを別に課金する場合です。 フォールバックはありません。プロバイダーが別に text の 数も報告していないかぎり、出力の合計の一部として output で課金されます。主要なプロバイダーの課金の仕方が それです。下を見てください。

キャッシュされたトークンは、一度だけ課金されます

請求額を多く見せる古典的なやり方は、キャッシュされたトークンを二度課金する ことです。一度はキャッシュの単価で、もう一度は、それをすでに含んでいる報告 済みの入力合計の一部として数えるのです。そのため、プロバイダーが内訳を報告 している場合は、その内訳が優先されます。mcpd は各計測項目をそれぞれの単価 で値付けし、残りだけを通常の入力の単価で課金します。

入力トークン 100 万、うち 90 万がキャッシュから読まれたと報告する claude-sonnet-4 の呼び出しは、同梱の価格表に対して次のように 値付けされます。

  • キャッシュ読み取り 900,000 を 100 万あたり $0.30 で、$0.27。
  • 残りの入力トークン 100,000 を 100 万あたり $3.00 で、$0.30。
  • 入力のコストは $0.57。報告された合計だけから出したなら $3.00 に なっていたところです。

プロバイダーが明示的な text の数を返す場合、その数がそのまま 残りとして使われます。返さない場合、残りは、報告された合計から計測項目の フィールドをすべて引いたものです。

ここに、名前を挙げておく価値のある穴が 1 つ残ります。価格表が単価を持たない 計測項目は、残りの一部としてしか課金されないので、プロバイダーが text の数も送っていた場合は、まったく課金されません。推論 トークンは、価格表がそれ自身の単価を与えていないときに、いつでもここに 落ちます。単価を 1 つ書けば直ります。画像トークンは常にここに落ちます。 価格表に与えられる画像の単価が無いからです。マルチモーダルの比重が大きい 処理では、この値は正確な額ではなく、低めの額として読んでください。

未知のモデルにはコストがありません。コストがゼロなのではありません

価格表にそのモデルの単価が無ければ、mcpd はコストのフィールドをまったく 付けずにスパンを保存します。ゼロを保存することはしません。

ゼロは主張です。この呼び出しは無料だった、という主張です。無いことは告白 です。この呼び出しの費用は分からない、という告白です。この 2 つは違う判断に つながり、後者を前者として報告する道具は、請求について嘘をついています。 同じ規則は読み出し経路にも通っています。スパンの合計が何も出ない実行は、 コストがゼロではなく、コストの値を持たないまま返されます。だからコストの 列が空欄なら、それは値付けされていないという意味であり、 無料という意味には決してなりません。

実務上の帰結は、身につけておく価値があります。価格表に無いモデルは、どの 合計からも抜けます。その支出は /v1/api/analytics/cost に現れ ず、その実行は、正の min_cost フィルターから除外されます。週の 合計が低すぎるように見えるときは、たいてい暇な週だったのではなく、解決でき ていないモデル id があります。

モデル id の解決

スパンに載る id は、あなたのクライアントが送ったそのままであり、 クライアントはそこに飾りを付けます。ゲートウェイはベンダー名を前に付け、 クラウドはリージョンを前に付け、プロバイダーはリリース日を後ろに留めます。 価格表は素のモデル名を鍵にしているので、検索は 4 つを順に試し、最初に当たった ところで止まります。

段階例
与えられたままの id、大文字小文字をそろえたもの GPT-4o は gpt-4o に当たります
最後のスラッシュより後の部分 openai/gpt-4o は gpt-4o に当たります
クラウドの id の、ドットで区切られた末尾 us.anthropic.claude-sonnet-4 は claude-sonnet-4 に当たります
末尾の日付を取り除いた id。接頭辞は、有っても無くてもかまいません openai/gpt-4o-2024-08-06 は gpt-4o に当たります

-YYYY-MM-DD と -YYYYMMDD のどちらの接尾辞も認識 します。4 つの段階すべてに外れることは、エラーではなく普通の結果です。上に 書いたとおり、コストが無いという意味になります。

同梱の価格表

mcpd は小さな組み込みの価格表を持っています。設定を 1 つもしなくても docker run が実際の値を出すためです。名前は builtin、通貨は USD で、そこから出たコストはすべて、その名前を 記録します。

モデル入力出力キャッシュ読み取りキャッシュ書き込み、5 分キャッシュ書き込み、1 時間
claude-opus-415.0075.001.5018.7530.00
claude-opus-4-115.0075.001.5018.7530.00
claude-opus-4-55.0025.000.506.2510.00
claude-sonnet-43.0015.000.303.756.00
claude-sonnet-4-53.0015.000.303.756.00
claude-haiku-4-51.005.000.101.252.00
claude-3-5-haiku0.804.000.081.001.60
gpt-4o2.5010.001.25入力と同じ入力と同じ
gpt-4o-mini0.150.600.075入力と同じ入力と同じ
gpt-4.12.008.000.50入力と同じ入力と同じ
gpt-4.1-mini0.401.600.10入力と同じ入力と同じ
o32.008.000.50入力と同じ入力と同じ
o4-mini1.104.400.275入力と同じ入力と同じ
gemini-2.5-pro1.2510.000.31入力と同じ入力と同じ
gemini-2.5-flash0.302.500.075入力と同じ入力と同じ
text-embedding-3-small0.020.00入力と同じ入力と同じ入力と同じ
text-embedding-3-large0.130.00入力と同じ入力と同じ入力と同じ

100 万トークンあたりの USD で、第三者のモデルカタログと最後に突き合わせた 時点の価格表の状態です。その日付は、価格表が as_of として記録 しています。Anthropic の項目が両方のキャッシュ書き込み単価を持っているのは、 デーモンが 1 時間の単価から 5 分の単価へフォールバックするからで、長いほうを 省いた価格表は、黙って過少請求になります。OpenAI はキャッシュへの書き込みに 課金しないので、そこでのキャッシュ書き込みは入力の単価で計算します。 gemini-2.5-flash は、音声入力の単価 1.00 も持っています。それ 以外の項目は、音声をテキストの単価で値付けします。 claude-haiku-4 はありません。Anthropic が提供している id は claude-haiku-4-5 であり、何にも解決しない id は、推測せずに 未値付けのままにします。

これは公開された定価であって、あなたの価格ではありません。交渉した単価が ある場合や、この表に無いモデルを動かしている場合、mcpd が見せる数字は推定 であり、推定として読むべきものです。価格表が短いのは意図したことです。長い 表は、より多くの箇所で古びていき、それに値するより強い正確さの印象を 与えます。

自分の価格表を渡すためのコマンドラインのフラグは、まだありません。価格表は サーバーの状態の一部で、今のところ差し替える方法は、mcpd をライブラリとして 組み込み、AppState::with_price_book に 1 つ渡すことです。価格表 は、id と、ISO 4217 の通貨と、モデル id から単価への対応表です。そこから出た 値にはすべて価格表の id が刻まれるので、後から 2 つの価格表を見分けられます。 1 つのプロジェクトの中では、価格の通貨をそろえてください。mcpd は実行の スパンをそのまま足し合わせ、通貨の換算はしません。

使った金額を読み出す

GET /v1/api/analytics/cost は、ある期間で金額がどこに使われた かに答えます。表計算ソフトへ何かを書き出す必要はありません。

curl -s 'http://localhost:4317/v1/api/analytics/cost?from=-7d&group_by=model'
パラメーター意味
from、to 期間。RFC 3339、または相対表記の短縮形です。既定は、今を終端とする 直近 7 日間です。
group_by 既定は model。ほかに provider、 entity_name、environment、 status、session_id、user_id、 service_name、name が使えます。
bucket 30s、5m、1h、1d の いずれか。省略すると合計だけになり、指定すると合計に加えて時系列も 返ります。
project どのプロジェクトを読むか。既定は、デーモンの既定のプロジェクトです。

どこに使われたか

# 先週の支出を、モデル別に。
curl -s --get http://localhost:4317/v1/api/analytics/cost \
  --data-urlencode 'from=-7d' \
  --data-urlencode 'group_by=model'

# 同じ週を日ごとの時系列で。変わった日が見えます。
curl -s --get http://localhost:4317/v1/api/analytics/cost \
  --data-urlencode 'from=-7d' \
  --data-urlencode 'group_by=model' \
  --data-urlencode 'bucket=1d'

グループは大きい順に返り、上限は 100 行です。バケットに分けた時系列の上限は 5,000 点です。

レスポンス

{
  "from": "2026-08-20T09:00:00Z",
  "to": "2026-08-27T09:00:00Z",
  "currency": "USD",
  "total_cost": 12.418264,
  "groups": [
    {
      "key": "claude-sonnet-4",
      "count": 1841,
      "error_count": 12,
      "total_cost": 9.612055,
      "input_tokens": 2903118,
      "output_tokens": 214477,
      "latency": { "mean": 1840.2, "max": 24193.0 }
    },
    {
      "key": "gpt-4o-mini",
      "count": 6204,
      "error_count": 3,
      "total_cost": 2.806209,
      "input_tokens": 9114882,
      "output_tokens": 388310,
      "latency": { "mean": 612.4, "max": 8801.0 }
    }
  ]
}

count に、細かい点が 1 つあります。model、 provider、entity_name でまとめる場合はスパンを 読むので、count はモデル呼び出しの数です。それ以外でまとめる 場合は実行の射影を読むので、count は実行の数です。どちらも役に 立ちますが、同じ数ではありません。片方をもう片方と比べることが、ここで いちばんしやすい間違いです。

このレスポンスの、グループごとのレイテンシは、平均と最大だけを持ちます。 パーセンタイルは GET /v1/api/analytics/summary から得られます。 こちらが、期間全体で計算します。

次に読むもの

コストは実行の一覧の 1 列であり、調査が実際に始まるのは、その一覧です。 実行を探す が min_cost と、支出による並べ替えを扱っています。値付けの前に ペイロードが捨てられているせいで数字がおかしく見える場合は、 サンプリング を見て ください。そもそも何が記録されるかを決めているのは、こちらです。この ページに出てくるフィールドはすべて、 データモデル に載っています。