mcpField
O
Otel

Otel

ローカル
npmjs.com開発ツール01 週間前に更新

Otel について

mcp-otelは、MCPサーバーの開発者やクライアント向けの小規模なライブラリです。リクエストメタデータのW3CトレースコンテキストをOpenTelemetryスパンにつなぎ、初期化やエクスポーターの選択はアプリケーションに任せます。

主な機能

  1. 01_meta経由のW3Cコンテキスト伝播
  2. 02ツールハンドラーをサーバースパンでラップ
  3. 03トレースコンテキストの抽出・注入
  4. 04スパンの状態と例外の記録
  5. 05カスタムスパン属性の設定

活用シーン

  1. 01ホスト、ツール、下流のスパンを連結
  2. 02選択したMCPツールハンドラーの計装
  3. 03MCPクライアントからのトレースコンテキスト転送

MCP 対応

MCPの_metaからtraceparent、tracestate、baggageを読み書きします。サーバーではツール呼び出しスパンを作成し、クライアントでは現在のトレースコンテキストをリクエストに注入できます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"otel": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"\\"
]
}
}
}
起動コマンドdocker run -i --rm '\'

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
oci\

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

StudioMeyer MCP Stack の一部 — マヨルカで開発 🌴 · ご利用の際は ⭐ をお願いします

mcp-otel

Model Context Protocol 用の W3C Trace Context ブリッジです。MCP の _meta フィールドを通じてトレースコンテキストを伝播し、OpenTelemetry のスパンを出力します。これにより、Host → MCP サーバー → ツール → 下流 HTTP と流れるリクエストが、Jaeger、Tempo、Honeycomb、Datadog で 1 つのつながったトレースとして表示されます。

npm CI OpenSSF Scorecard License: MIT


これが作られた理由

MCP の 2026-07-28 のリリース候補版で、MCP の分散トレーシングが確定しました。

  • SEP-414 では、プレフィックスのない _meta キー traceparent、tracestate、baggage を、W3C Trace Context と W3C Baggage 用に予約しています。これらのキーはすべてのリクエストの params._meta に含まれ、MCP のトランスポートは変更せずにそのまま引き継ぐ必要があります。
  • SEP-2577 では、MCP のロギング機能が非推奨となり、今後のオブザーバビリティの手段として OpenTelemetry が示されました。

仕様に関する記事:https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/

つまり、プロトコルによって、トレースコンテキストの格納場所と使用するテレメトリーシステムは定められました。しかし、実際の連携を行う小さなライブラリはありませんでした。呼び出し元のコンテキストを _meta から読み取り、ツール呼び出しに適切な親を持つ OpenTelemetry スパンを開始し、下流の呼び出しをそのスパンにつなげるライブラリです。それが mcp-otel です。

意図的に薄いレイヤーとして作られています。OpenTelemetry の設定、エクスポーターの同梱、トレーサーの隠蔽は行いません。サンプリング、リソース、エクスポーターは引き続き自由に制御できます。mcp-otel が行うのは、_meta とスパンの橋渡しだけです。

インストール

npm install mcp-otel @opentelemetry/api
# @modelcontextprotocol/sdk is an optional peer — only needed if you use the
# tool-handler wrapper against the SDK (the low-level helpers don't import it).

ピア依存関係:

パッケージ範囲必須?
@opentelemetry/api^1.9.0はい
@modelcontextprotocol/sdk>=1.10.0 <2任意(instrumentToolHandler の extra の形式でのみ使用)

Node 20 以上。ESM と CommonJS の両方を提供しています。

クイックスタート — サーバー側

起動時に一度だけ OpenTelemetry を設定します(通常の OTel ブートストラップです。mcp-otel は設定を行いません)。その後、各ツールハンドラーをラップします。

import { instrumentToolHandler } from "mcp-otel";
import { z } from "zod";

server.registerTool(
  "weather.lookup",
  { description: "Current weather", inputSchema: { city: z.string() } },
  // The only change: wrap the handler. Same (args, extra) => result signature.
  instrumentToolHandler("weather.lookup", async ({ city }) => {
    // trace.getActiveSpan() here is the MCP server span.
    // Any span you start, or any downstream fetch that injects the active
    // context, nests under it automatically.
    return { content: [{ type: "text", text: `Weather for ${city}` }] };
  }),
);

instrumentToolHandler は次の処理を行います。

  • 呼び出し元の _meta から traceparent / tracestate / baggage を読み取ります (公開されている SDK 1.x の形式である extra._meta と、extra.mcpReq._meta を確認します)。
  • 呼び出し元のスパンを親とする、tools/call <toolName> という名前の SERVER スパンを開始します。
  • OTel コンテキストを通じて、そのスパンをアクティブにした状態でハンドラーを実行します。
  • スパンを OK / ERROR ステータスで終了し、スローされた例外を記録します。

スパンに設定される属性:mcp.method("tools/call")、mcp.tool.name、mcp.request.id、および利用可能な場合は mcp.session.id。gen_ai.system などの GenAI 規約に沿った属性を設定するには、attributes を渡します。

明示的なプリミティブを使う場合は、_meta オブジェクトを直接扱える runInToolSpan を使用します。

import { runInToolSpan } from "mcp-otel";

const result = await runInToolSpan(
  meta,                                   // request.params._meta
  { toolName: "weather.lookup", requestId },
  async (span) => {
    span.setAttribute("weather.city", city);
    return doWork(city);
  },
);

クイックスタート — クライアント側

MCP クライアントを作成する場合は、サーバーがトレースを引き継げるよう、アクティブなトレースコンテキストをリクエストの _meta に注入します。

import { injectTraceContext } from "mcp-otel";

const result = await client.callTool({
  name: "weather.lookup",
  arguments: { city: "Palma" },
  _meta: injectTraceContext({}), // writes traceparent/tracestate/baggage from the active context
});

injectTraceContext(meta, context?) は _meta オブジェクトを変更して返します。デフォルトでは、現在アクティブな OpenTelemetry コンテキストを使用します。既存の _meta キー(progressToken など)は保持されます。

Jaeger に送信する

mcp-otel は標準の OpenTelemetry スパンを出力するため、どのエクスポーターでも使用できます。最小限の Jaeger セットアップ:

docker run -d --name jaeger \
  -p 16686:16686 -p 4318:4318 \
  jaegertracing/all-in-one
// otel-setup.ts — import this once, before anything else.
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";

const sdk = new NodeSDK({
  resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: "my-mcp-server" }),
  traceExporter: new OTLPTraceExporter({ url: "http://localhost:4318/v1/traces" }),
});
sdk.start();

NodeSDK は AsyncLocalStorageContextManager をインストールします。これにより、mcp-otel はアクティブなスパンを下流の呼び出しに伝播できます。http://localhost:16686 を開くと、host → tools/call <name> → downstream がひとつのトレースとして表示されます。

コンテキスト伝播に関する注意: 下流スパンの自動ネストには、コンテキストマネージャーがインストールされている必要があります。これは NodeSDK / NodeTracerProvider.register() が行う処理です。コンテキストマネージャーがないプロセス(例:素の BasicTracerProvider)でも、スパンは作成され、呼び出し元を親として正しく設定されますが、ハンドラー内の context.active() にはスパンが含まれません。これは標準の OpenTelemetry の契約であり、このライブラリ特有の挙動ではありません。

実行可能な例

インフラ不要の例(メモリー内エクスポーターを使用し、スパンツリーを出力します)は、examples/connected-trace.mjs にあります。

npm run build
node examples/connected-trace.mjs

次のように出力されます。

- host.chat-turn [INTERNAL]
  - tools/call weather.lookup [SERVER]
    - GET /weather [CLIENT]

All 3 spans share one traceId: yes

実際の SDK の配線は examples/mcp-server.ts にあります。

API リファレンス

計装
  • instrumentToolHandler(toolName, handler, options?) → ラップされたハンドラー。(args, extra) => result としてそのまま使用できるラッパーです。オプション:method(デフォルトは "tools/call")、tracer、attributes、および抽出関数のオーバーライドである getMeta / getRequestId / getSessionId。
  • runInToolSpan(meta, options, body) → Promise<T>。低レベルのプリミティブです。meta のトレースコンテキストを親とする SERVER スパン内で body(span) を実行します。オプション:toolName、method、requestId、sessionId、attributes、tracer。
伝播ヘルパー
  • extractTraceContext(meta, base?) → Context。_meta(traceparent + tracestate + baggage)から OTel の親コンテキストを構築します。決定論的な動作のため、base のデフォルトは ROOT_CONTEXT です。
  • injectTraceContext(meta, context?) → Meta。context(デフォルトはアクティブなコンテキスト)のトレースキーを _meta に書き込みます。meta を変更し、返します。
  • parseTraceparent(s) → SpanContext | null。W3C 準拠のパースを行います。バージョン 00 は長さを厳密に検証します(フィールドが正確に 4 つ)。より高いバージョンは前方互換性を考慮してパースされます(仕様に従い、最初の 4 フィールドを読み取り、後続のフィールドは無視します)。これにより、Trace Context の進化に合わせて引き続き動作します。不正な値、バージョン ff、またはすべてゼロの値(無効な trace-id / parent-id)の場合は null を返します。結果の isRemote は true です。
  • formatTraceparent(spanContext) → string | null。バージョン 00 の traceparent にシリアライズします。スパンコンテキストが無効な場合は null を返します。
  • spanContextToContext(spanContext, base?) → Context。すでに保持しているスパンコンテキストを、インジェクション用のコンテキストにラップします。
  • traceContextFields() → string[]。このライブラリが読み書きする _meta のキーです(_meta を転送する前にこれらを除去する場合に便利です)。
定数

TRACEPARENT_META_KEY、TRACESTATE_META_KEY、BAGGAGE_META_KEY、TRACE_META_KEYS、および属性キー ATTR_MCP_METHOD、ATTR_MCP_TOOL_NAME、ATTR_MCP_REQUEST_ID、ATTR_MCP_SESSION_ID。

_meta であり、HTTP ヘッダーではない理由

MCP は Streamable HTTP で実行できるのに、通常のウェブサービスのように HTTP リクエストヘッダーから traceparent を読み取らないのはなぜか、と疑問に思うかもしれません。

  • MCP はトランスポートに依存しません。 同じサーバーロジックを stdio、Streamable HTTP などで実行できます。stdio にはヘッダーがありません。トレースコンテキストを _meta に格納すれば、すべてのトランスポートで同じように伝播できます。これこそが、仕様で HTTP に頼るのではなく、_meta 内に これらのキーを確保した理由です。
  • 1 つの HTTP 接続で複数の論理リクエストを処理します。 Streamable HTTP では、1 つの長時間接続で複数の JSON-RPC メッセージを多重化します。トランスポートレベルのヘッダーが表すのは 接続 であり、各ツール呼び出しではありません。トレースコンテキストは個々のリクエストに属します。MCP ではそのリクエストは JSON-RPC メッセージであり、メッセージごとのメタデータは _meta です。
  • ホストが HTTP クライアントであるとは限りません。 ルートスパンを所有するもの(LLM ホスト/エージェント)と、ソケットを開くものは、別のプロセスである場合があります。_meta は論理リクエストとともにそれらのホップを越えて伝播しますが、ホップごとの HTTP ヘッダーではそうなりません。

つまり _meta は、リクエストごとに設定でき、かつトランスポートに依存しない唯一の場所です。そのため SEP-414 は _meta を標準化し、このライブラリもそこで読み書きします。

対応しないこと

  • OpenTelemetry の初期化、エクスポーターの選択、サンプラーの設定は行いません。それらはアプリの役割です。また、これらを対象外にすることで、SDK 側のバージョンに縛られません。
  • トランスポートを自動計装したり、SDK にグローバルなパッチを適用したりはしません。ツールハンドラーごとに明示的に有効にするか、ヘルパーを自分で呼び出してください。
  • メトリクスやログは生成しません。SEP-2577 の OTel 方針に従い、スパンのみを扱います。

StudioMeyer MCP ツールキットの一部

MCP サーバーの構築と運用に役立つ、用途を絞った本番品質のツール群です。自由に組み合わせてお使いください。

  • mcp-armor — ランタイム防御サイドカー:ツール呼び出しをスキャンし、署名済みマニフェストを検証して、既知の悪意ある CVE をブロックします
  • mcp-gauntlet — デプロイ前に使う mcp-fuzz(スキーマ対応ファザー)と mcp-storm(負荷テスター)
  • mcp-otel (このツール) — W3C Trace Context → OpenTelemetry ブリッジ
  • mcp-cache-kit — リークを防ぐ SEP-2549 キャッシュ(ttlMs + cacheScope)
  • skilldoctor — エージェントのスキルファイル用リンター + セキュリティスキャナー

ライセンス

MIT © StudioMeyer

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。