mcpField
O
OTC Pricing MCP

OTC Pricing MCP

ローカル
github.com/seaser0クラウド・インフラ01 日前に更新

OTC Pricing MCP について

OTC Pricing MCPは、Open Telekom Cloudの料金とドキュメントを検索するオープンソースのMCPサーバーです。STDIOとSSEに対応し、料金照会、コスト見積もり、課金方式の比較、索引化された文書の検索を提供します。

主な機能

  1. 01サービスとリージョン別の料金照会
  2. 02CPUとメモリによるコンピュート仕様の検索
  3. 03リソースの月額コスト見積もり
  4. 04従量課金と予約料金の比較
  5. 05OTC文書の検索とセクション取得
  6. 06ヘルスチェックとPrometheusメトリクス

活用シーン

  1. 01要件に合うECS仕様の検索
  2. 02クラウドリソースの月額コスト見積もり
  3. 03従量課金と予約プランの比較
  4. 04OTCサービスやAPI文書の参照

MCP 対応

MCPツールを通じて、OTCの料金データと索引化されたユーザーマニュアル、APIリファレンスを提供します。MCPクライアントはSTDIOまたはSSEで接続できます。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"seaser0-otc-pricing": {
"command": "uvx",
"args": [
"otc-pricing-mcp"
]
}
}
}
起動コマンドuvx otc-pricing-mcp

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

パッケージ
pypiotc-pricing-mcp0.1.1

ツール

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

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

詳細

OTC 料金 MCP サーバー

CI Release License Python

Open Telekom Cloud(OTC)料金計算 API向けのオープンソース Model Context Protocol(MCP) サーバーです。

構造化ログ、Prometheus メトリクス、ヘルスチェックなど、完全な可観測性を備え、OTC の料金データを Claude やその他の LLM クライアントに提供します。

ステータス:v0.1.3 — STDIO + SSE トランスポート、Kubernetes デプロイ、完全な可観測性


MCP とは?

Model Context Protocol は、LLM アプリケーション(Claude など)が外部のツールやデータソースとやり取りできるようにする標準規格です。このサーバーは 2 種類のトランスポートに対応しています。

トランスポート仕組み最適な用途
STDIOClaude がサブプロセスとしてサーバーを起動し、stdin/stdout 経由で通信しますローカルの Claude Desktop、CLI ツール
SSEHTTP 経由の Server-Sent Events — Claude が URL に接続しますリモート/ホスト型デプロイ、ウェブクライアント

このサーバーを使うと、お好みのトランスポート経由で、9 つの専用ツールから OTC の料金データやユーザーマニュアル/API リファレンスのドキュメントに Claude がアクセスできます。


これで何ができますか?

ユースケースの例:

  • Claude に「eu-de で CPU 4 個、RAM 8GB の最安の ECS インスタンスを探して」と尋ねます。
  • Claude が find_compute_flavor ツールを呼び出し、料金データを取得して回答します。
  • 「S3 ストレージの PAYG と 12 か月予約料金を比較して」と尋ねます。
  • Claude が compare_billing_models ツールを呼び出して分析し、節約額を提示します。

クイックスタート

1. インストール

要件:Python 3.12+

# Clone the repository
git clone https://github.com/seaser0/otc-pricing-mcp.git
cd otc-pricing-mcp

# Install dependencies
uv sync

# Run the server
python -m otc_pricing_mcp

表示される内容:

{"event": "mcp_server_starting", "transports": ["stdio", "sse"], "port": 8080, ...}
{"event": "mcp_server_ready", "status": "accepting_connections", ...}

サーバーは stdin/stdout と http://localhost:8080/sse の両方で MCP 接続を待ち受けるようになります。

2. MCP クライアントを接続する

オプション A — STDIO(ローカル、Claude Desktop)

{
  "mcpServers": {
    "otc-pricing": {
      "command": "python",
      "args": ["-m", "otc_pricing_mcp"],
      "env": {
        "LOG_LEVEL": "INFO",
        "METRICS_PORT": "8080"
      }
    }
  }
}

オプション B — SSE(リモート、Kubernetes)

SSE トランスポートに対応する任意の MCP クライアントで、ホストされたエンドポイントを指定します。

{
  "mcpServers": {
    "otc-pricing": {
      "url": "https://mcp-otc-pricing.example.com/sse"
    }
  }
}

または、サーバーの実行中にローカルでテストします。

# In a second terminal:
curl -N http://localhost:8080/sse
# event: endpoint
# data: /messages/?session_id=<uuid>
3. ツールを使い始める

接続すると、Claude は利用可能な 7 つのツールを呼び出せます。以下のツールリファレンスセクションを参照してください。


ツールリファレンス

このサーバーは、さまざまな料金照会に対応する 7 つの MCP ツールを提供します。

1. list_services

目的:利用可能な OTC サービスをすべて取得します。

入力:なし

出力:サービス名とメタデータのリスト

Claude の使用例:

"What OTC services are available for pricing?"

2. list_regions

目的:利用可能な OTC リージョンを取得します。

入力:なし

出力:リージョンコードのリスト(eu-de、eu-nl、eu-ch2 など)

Claude の使用例:

"What regions does OTC support?"

3. get_service_schema

目的:サービスでフィルタリング/返却できる列を取得します。

入力:

  • service(文字列):サービス名(例:"ecs"、"evs"、"obs"、"s3"、"rds")

出力:フィルタリング可能な列名と返却可能な列名を含むスキーマ

Claude の使用例:

"What columns can I filter on for ECS pricing?"

4. query_pricing

目的:柔軟なフィルタリングで料金データを照会します。

入力:

  • services(配列):サービス名のリスト(例:["ecs", "evs"])
  • region(文字列、省略可能):リージョンでフィルタリングします(例:"eu-de")
  • max_results(整数、省略可能):返す結果の最大数(デフォルト:5000)

出力:フィルターに一致する料金データ行

Claude の使用例:

"Show me ECS and EVS pricing in the eu-de region"

5. find_compute_flavor

目的:vCPU/RAM/OS に基づいてコンピューティング(ECS)インスタンスを検索します。

入力:

  • v_cpu(整数):仮想 CPU 数
  • ram_gb(数値):RAM 容量(GiB)
  • os(文字列、任意):オペレーティングシステム(Linux、Windows など)
  • region(文字列、任意):リージョン(デフォルト:eu-de)

出力:料金付きの一致する ECS インスタンスタイプ

Claude の使用例:

"Find a Linux ECS instance with 4 CPUs and 16GB RAM in eu-nl"

6. estimate_monthly_cost

目的:複数のリソースの月額費用を計算します。

入力:

  • items(配列):以下を含むリソース:
    • id(文字列):製品 ID(例:"OTC_S3M1_LI")
    • quantity(数値、任意):ユニット数(デフォルト:1)
    • hours_per_month(数値、任意):使用時間(デフォルト:730)

出力:明細付きの費用と月額合計

Claude の使用例:

"Calculate monthly cost for 100GB S3 storage and an ECS instance"

7. compare_billing_models

目的:PAYG とリザーブドインスタンスの料金を比較します。

入力:

  • product_id(文字列):製品 ID(例:"OTC_S3M1_LI")
  • quantity(数値、任意):数量(デフォルト:1)
  • hours_per_month(数値、任意):使用時間(デフォルト:730)

出力:PAYG、12 か月、24 か月、36 か月のリザーブド料金の比較

Claude の使用例:

"Compare PAYG vs 12/24/36 month reserved pricing for ECS"
8. search_otc_docs

目的:インデックス化された OTC ユーザーマニュアルと API リファレンスを全文検索します。

入力:

  • query(文字列):検索語(BM25 順位付け、トークンの AND 検索)
  • scope(文字列、任意):public | swiss | both(デフォルト:both)
  • service(文字列、任意):単一のサービスリポジトリに絞り込みます(例:elastic-cloud-server)
  • top_k(整数、任意):1~50、デフォルトは 5

出力:{url, title, h2, h3, snippet, service, cloud, upstream_commit} の順位付けされた一覧。 インデックスはパッケージに同梱され、上流の opentelekomcloud-docs/<service> Sphinx/RST リポジトリ(Apache-2.0)から毎週再構築されます。実行時に Anubis によってアクセスが制限された docs.otc.t-systems.com の HTML にアクセスすることはありません。

Claude の使用例:

"Find the OTC docs page that explains S3-flavor ECS specifications"
9. get_otc_doc_section

目的:インデックス化されたドキュメントページ(またはそのセクション)の本文を Markdown として取得します。

入力:

  • url(文字列):search_otc_docs が返す正規 URL(#anchor の有無は問いません)
  • section(文字列、任意):H2/H3 見出しによるフィルター(大文字と小文字を区別しない部分一致)

出力:{url, title, sections: [{h2, h3, anchor, body}, ...], matched, ...}

Claude の使用例:

"Show me the EVS Disk Types and Performance section"

設定

環境変数

環境変数を使用してサーバーの動作を制御します。

変数デフォルト説明
LOG_LEVELINFOログレベル:DEBUG、INFO、WARNING、ERROR
METRICS_PORT8080メトリクス/ヘルスエンドポイントのポート
METRICS_HOST0.0.0.0HTTP サーバーのバインドアドレス(コンテナを使用しない場合は 127.0.0.1 に設定)
OTC_PRICING_API_BASEhttps://calculator.otc-service.com/en/open-telekom-price-api/OTC API エンドポイント
OTC_DOCS_DB(自動)ドキュメント FTS5 インデックスのパスを上書きします(デフォルト:同梱の data/otc_docs.sqlite3)

例:

LOG_LEVEL=DEBUG METRICS_PORT=9090 python -m otc_pricing_mcp

可観測性:メトリクスとログ

このサーバーは、問題のデバッグやパフォーマンスの監視に役立つ、本番環境向けの可観測性を備えています。

構造化ログ(JSON)

すべての動作が JSON として記録されるため、ログを集約や分析のために機械で読み取ることができます。

DEBUG ログでサーバーを起動します:

LOG_LEVEL=DEBUG python -m otc_pricing_mcp 2>&1

次のような JSON ログが出力されます:

{"timestamp": "2026-05-06T18:00:00.123456Z", "event": "tool_invocation_start", "tool": "query_pricing", "request_id": "550e8400-e29b-41d4-a716-446655440000", "arguments": {"services": ["ecs"]}}

{"timestamp": "2026-05-06T18:00:00.234567Z", "event": "upstream_request_start", "service": "ecs", "request_id": "550e8400-e29b-41d4-a716-446655440000"}

{"timestamp": "2026-05-06T18:00:00.345678Z", "event": "upstream_request_success", "service": "ecs", "request_id": "550e8400-e29b-41d4-a716-446655440000", "status_code": 200, "duration_seconds": 0.111, "attempt": 1, "items_returned": 42}

{"timestamp": "2026-05-06T18:00:00.456789Z", "event": "tool_invocation_success", "tool": "query_pricing", "request_id": "550e8400-e29b-41d4-a716-446655440000", "duration_seconds": 0.333}

すべてのログに含まれる主なフィールド:

  • timestamp:イベントが発生した日時(ISO 8601)
  • event:発生した内容(tool_invocation_start、upstream_request_success など)
  • request_id:このリクエストの一意の ID(関連するすべてのログで共通)
  • イベントに応じたカスタムフィールド

ログは stderr に出力されるため、ファイルまたはログアグリゲーターにリダイレクトできます:

python -m otc_pricing_mcp 2>/var/log/otc-pricing-mcp.log

jq にパイプして整形表示します:

python -m otc_pricing_mcp 2>&1 | jq .
HTTP エンドポイント(ポート 8080)

uvicorn サーバーは、すべてのエンドポイントをポート 8080 で公開します。

パスメソッド説明
/sseGETMCP SSE トランスポート — MCP クライアントはこちらに接続します
/messages/POSTMCP SSE メッセージハンドラー(クライアントが内部で使用します)
/healthzGET稼働確認プローブ — プロセスが起動していれば常に 200 を返します
/readyzGET準備状態プローブ — OTC API に到達可能な場合は 200、そうでない場合は 503 を返します
/metricsGETテキスト形式の Prometheus メトリクス

ヘルスチェック:

# Liveness check (always 200 if process is up)
curl http://localhost:8080/healthz
# {"status": "ok", "service": "otc-pricing-mcp"}

# Readiness check (verifies OTC API is reachable)
curl http://localhost:8080/readyz
# {"status": "ready", "upstream": "ok", "api_response_time": 0.042}

Prometheus メトリクス:

curl http://localhost:8080/metrics

Prometheus 形式のメトリクスを返します:

# HELP otc_pricing_mcp_requests_total Total MCP tool requests (success and failure)
# TYPE otc_pricing_mcp_requests_total counter
otc_pricing_mcp_requests_total{status="success",tool="query_pricing"} 5.0
otc_pricing_mcp_requests_total{status="error",tool="query_pricing"} 1.0

# HELP otc_pricing_mcp_request_duration_seconds MCP tool request duration in seconds
# TYPE otc_pricing_mcp_request_duration_seconds histogram
otc_pricing_mcp_request_duration_seconds_bucket{le="0.005",tool="query_pricing"} 0.0
otc_pricing_mcp_request_duration_seconds_bucket{le="0.01",tool="query_pricing"} 1.0
...

# HELP otc_pricing_mcp_upstream_requests_total Total upstream OTC API requests (success and failure)
# TYPE otc_pricing_mcp_upstream_requests_total counter
otc_pricing_mcp_upstream_requests_total{service="ecs",status="success"} 10.0
otc_pricing_mcp_upstream_requests_total{service="ecs",status="error"} 2.0
...

利用可能なメトリクス:

  • otc_pricing_mcp_requests_total{tool, status}:ツール呼び出し回数
  • otc_pricing_mcp_request_duration_seconds{tool}:ツールの実行時間
  • otc_pricing_mcp_upstream_requests_total{service, status}:API 呼び出し回数
  • otc_pricing_mcp_upstream_duration_seconds{service}:API 呼び出しのレイテンシ

Prometheus の使用方法:

prometheus.yml に追加します:

scrape_configs:
  - job_name: 'otc-pricing-mcp'
    static_configs:
      - targets: ['localhost:8080']

次に、Prometheus でクエリを実行します:

rate(otc_pricing_mcp_requests_total[5m])  # Requests per second
histogram_quantile(0.95, otc_pricing_mcp_request_duration_seconds_bucket)  # p95 latency

デバッグガイド

問題:API 呼び出しが遅い

ログを確認します:

LOG_LEVEL=DEBUG python -m otc_pricing_mcp 2>&1 | jq 'select(.event == "upstream_request_success") | {service, duration_seconds}'

メトリクスを確認します:

curl http://localhost:8080/metrics | grep upstream_duration_seconds
問題:ツールが失敗する

エラーログを確認します:

LOG_LEVEL=DEBUG python -m otc_pricing_mcp 2>&1 | jq 'select(.event == "tool_invocation_error")'

エラーログの例:

{
  "event": "tool_invocation_error",
  "tool": "query_pricing",
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "error": "list index out of range",
  "error_type": "IndexError",
  "duration_seconds": 0.001,
  "exc_info": true
}
問題:OTC API に到達できない

準備状態エンドポイントを確認します:

curl -v http://localhost:8080/readyz
# HTTP/1.1 503 Service Unavailable
# {"status": "not_ready", "upstream": "unreachable", "error": "..."}

メトリクスを確認します:

curl http://localhost:8080/metrics | grep upstream_requests_total
# Will show increased error counts
問題:リクエストの詳細なトレースが必要

request_id を使用してリクエストを追跡します:

# Get the request_id from any log
LOG_LEVEL=DEBUG python -m otc_pricing_mcp 2>&1 | jq 'select(.request_id == "550e8400-e29b-41d4-a716-446655440000")'

このリクエストのすべてのログが順番に表示されます:

  1. tool_invocation_start
  2. upstream_request_start
  3. upstream_request_success(items_returned を含む)
  4. tool_invocation_success

ローカルでの実行(開発)

セットアップ
# Clone repo
git clone https://github.com/seaser0/otc-pricing-mcp.git
cd otc-pricing-mcp

# Install with dev dependencies
uv sync

# Run tests
uv run pytest tests/ -v

# Check code quality
uv run ruff check src/
uv run mypy src/ --strict
開発モードでの実行
# With debug logging
LOG_LEVEL=DEBUG python -m otc_pricing_mcp

# In another terminal, test the endpoints
curl http://localhost:8080/healthz | jq .
curl http://localhost:8080/metrics

本番環境での実行(Docker)

イメージのビルド
docker build -t otc-pricing-mcp:latest .
コンテナーの実行
docker run \
  --name otc-pricing-mcp \
  -e LOG_LEVEL=INFO \
  -e METRICS_PORT=8080 \
  -p 8080:8080 \
  otc-pricing-mcp:latest
Kubernetes デプロイ

マニフェスト一式(Deployment、Service、Ingress、NetworkPolicy、ServiceMonitor、PodDisruptionBudget)については、deploy/kubernetes/ を参照してください。

Kubernetes 上でセルフホストする場合は、リモートクライアントを Ingress のホスト名に接続します:

https://mcp-otc-pricing.example.com/sse

主な機能:

  • 非 root ユーザー、読み取り専用のルートファイルシステム
  • リソース制限(CPU 100m~500m、RAM 128Mi~512Mi)
  • 稼働確認プローブ:ポート 8080 で GET /healthz
  • 準備状態プローブ:ポート 8080 で GET /readyz
  • NetworkPolicy:nginx コントローラーからの Ingress のみ許可し、DNS と OTC API への egress を許可
  • Prometheus によるスクレイピング用の ServiceMonitor
  • selfHeal: true および prune: true を設定して ArgoCD で管理

アーキテクチャ

リクエストフロー
Claude Client
    │
    ├─ STDIO transport (local)      ──┐
    │  stdin/stdout                   │
    │                                 ▼
    └─ SSE transport (remote)      MCP Server (server.py)
       GET  /sse                     - List tools
       POST /messages/               - Route tool calls
                                     - Log invocations
                                     - Record metrics
                                         │
                                         ▼
                                   HTTP Client (client.py)
                                     - Build request
                                     - Retry logic
                                     - Parse response
                                         │
                                         ▼
                                   OTC Price Calculator API

どちらのトランスポートも同じ MCP Server インスタンスを共有し、同じ asyncio イベントループ内で並行して実行されます。

コンポーネント概要
コンポーネント目的
__main__.pyエントリーポイント — STDIO と uvicorn SSE を並行して実行します
server.pyMCP サーバー。ツール呼び出しをルーティングし、呼び出しをログに記録します
client.pyOTC API 用 HTTP クライアント。リトライ処理と API ログ記録を行います
tools/ツールの実装(検出、価格設定、見積もり)
observability/http_server.pyStarlette アプリ — SSE トランスポートとヘルス/メトリクスのルート
observability/ログ、Prometheus メトリクス、リクエストコンテキスト
models.pyデータモデル(Pydantic で検証)
normalize.py価格の解析と整形

機能強化のアイデア(今後の開発)

ストーリー 0~9 は完了しています。以下は v1.0 以降の機能強化です:

拡張アイデア

キャッシュ

  • API 負荷を軽減するため、価格データを N 秒間キャッシュします
  • Redis またはインメモリキャッシュのオプション
  • キャッシュ無効化戦略

高度なクエリ

  • フィルタリングオプションの追加(例:価格帯、契約期間)
  • 価格、CPU、RAM による並べ替え
  • サービスごとの価格の集計(最小値/最大値/平均値)

コスト分析ツール

  • 過去の価格推移
  • コスト異常の検出
  • 推奨エンジン(適正なリソースサイズへの調整)

マルチクラウド対応

  • AWS 価格 API との統合
  • Azure 価格 API との統合
  • クラウド間のコスト比較

ユーザー設定

  • お気に入りのサービス/リージョンを保存
  • カスタム価格アラート
  • プロジェクトごとの予算管理

エラー回復の改善

  • ジッターを加えた指数バックオフ(固定の指数バックオフの代わり)
  • サーキットブレーカーパターン
  • API 障害時にキャッシュデータへフォールバック

パフォーマンスの最適化

  • クエリ結果のページネーション
  • データベースキャッシュレイヤー
  • 大規模データセット向けのストリーミングレスポンス

可観測性の強化

  • 分散トレーシング(OpenTelemetry)
  • カスタムビジネスメトリクス(算出コスト、サービスごとのクエリ数)
  • ログ集約との統合(Loki、ELK)
  • アラートルール(Prometheus Alertmanager)

テストの改善

  • 負荷テスト(k6、Locust)
  • カオステスト(障害シナリオ)
  • OTC API とのコントラクトテスト

API の安定性

  • API バージョニング(v1、v2)
  • 廃止ポリシー
  • 後方互換性の保証

貢献

皆さまからの貢献を歓迎します!以下については CONTRIBUTING.md をご覧ください。

  • 開発環境のセットアップ
  • コードスタイル(ruff、mypy --strict)
  • テスト要件(カバレッジ付きで 53 件以上のテスト)
  • セキュリティスキャン(bandit、cyclonedx-bom)
  • コミットメッセージの規約

簡単な PR チェックリスト:

  • テストに合格する:uv run pytest tests/
  • Lint に合格する:uv run ruff check src/
  • 型チェックに合格する:uv run mypy src/ --strict
  • セキュリティスキャンに合格する:uv run bandit -r src/
  • 意味のあるコミットメッセージ

ライセンス

Apache License 2.0 — LICENSE ファイルをご覧ください。

著作権:seaser0 ([email protected])


ヘルプ

質問や問題がありますか?

  1. 上記の デバッグガイド を確認してください
  2. GitHub Issue を作成してください:https://github.com/seaser0/otc-pricing-mcp/issues
  3. 次のコマンドでログを確認してください:LOG_LEVEL=DEBUG python -m otc_pricing_mcp 2>&1 | jq .

セキュリティ問題を報告しますか? 責任ある情報開示については SECURITY.md をご覧ください。


プロジェクトの状況

ストーリー機能状況
0プロジェクトのセットアップ、API クライアント、データモデル✅ 完了
1カタログ探索ツール✅ 完了
2価格クエリツール✅ 完了
3複数サービスへのファンアウト✅ 完了
4包括的なテスト✅ 完了
5セキュリティとコンテナの強化✅ 完了
6CI/CD パイプライン(GHCR イメージ、PyPI、SBOM、GitHub リリース)✅ 完了
7可観測性(構造化ログ、Prometheus メトリクス、ヘルスプローブ)✅ 完了
8ArgoCD デプロイ(Kubernetes、SSE トランスポート、リモートエンドポイント)✅ 完了
9オープンソースドキュメント(README、server.json、コミュニティドキュメント)✅ 完了

アーキテクチャ上の決定

詳しいドキュメントについては docs/ ディレクトリをご覧ください。

  • docs/ci-cd.md — CI/CD ワークフローの詳細
  • docs/deployment.md — デプロイガイド
  • docs/security.md — セキュリティ機能と考慮事項

seaser0 が ❤️ を込めて作成

最終更新日:2026-05-07

コメント

MCP は初めてですか?

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

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