エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

GCPのテレメトリーのMCPサーバーを作ってボトルネックを発見する

AI・機械学習チームの北川(@kitagry)です。 このブログはAI・機械学習チームブログリレー1日目の記事です。

最近Claude Codeがとても流行っている気がしますね。 Vimmerである僕としてはCLIで使えるClaude Codeはとてもありがたいです。 NeovimでもDiffを出したり出来るclaudecode.nvimをとても愛用しています。

カメラを見つめる猫 ※本編には関係ありません

はじめに

オブザーバビリティは世界的に注目されています。 オブザーバビリティとはシステムの出力を調べることによって、システムの内部状態を理解する能力のことです。 ソフトウェアの文脈ではトレース・メトリクス・ログを含むテレメトリーデータを計測し、そこからシステムの内部状況を理解できることを意味します。

今回は次の4つのサービスからテレメトリーデータを取得するMCPサーバーを作成しました。

  • Cloud Profiler
  • Cloud Trace
  • Cloud Logging
  • Cloud Monitoring

github.com

MCPサーバーの実装編

MCPサーバーの作り方については様々なライブラリやブログが出ているのでそちらに譲ることとします。 ライブラリや言語を指定すれば、Claude Codeやらがほとんど書いてくれるので特に人間が考えることは少ないと思います。 最初は言語もライブラリも指定せずに実装するように言ったら変な方向で実装を始めたので、すぐに止めてGo言語とmark3labs/mcp-goというライブラリを利用するように指示しました。 GCP系のリソースのライブラリが豊富な点からGo言語を指定しました。

細かい話は他ブログに譲りつつも個人的に面白いなと思った点をいくつか挙げておきます。

利用方法を明示的に書く

MCPサーバーを作成するにはまず呼び出せる機能の定義を書いていきます

例)

listTimeSeresTool := mcp.NewTool("list_time_series",
    mcp.WithDescription("List time series data from Cloud Monitoring"),
    mcp.WithString("filter",
        mcp.Required(),
        mcp.Description(`A [monitoring filter](https://cloud.google.com/monitoring/api/v3/filters) that specifies which time series should be returned.  The filter must specify a single metric type, and can additionally specify metric labels and other information. For example:

metric.type = "compute.googleapis.com/instance/cpu/usage_time" AND
    metric.labels.instance_name = "my-instance-name"
        `),
    ),
    ...
)

この定義を見ながらAI AgentがどのMCPサーバーの機能を利用するかを決めるわけです。 つまり、この定義の説明文が不足していたりすればサーバーを利用してくれなかったり、的はずれな引数指定をしてくるわけです。 説明を如何に充足させるかで良いMCPサーバーになるかが決まると言えます。

上の例ではfilter引数がありますが、これはCloud Monitoringで見たいメトリクスの条件クエリを指定する引数です。 当初Claude Codeで実装したときにはDescriptionは最低限しか書かれていませんでした*1

mcp.Description("Filter expression (e.g., 'span_name_prefix:\"api\"')")

この状態で利用するとMCPとして利用したときにfilterの文法が間違っているなどのエラーが起きてしまいました。 そこで1つのmetric typeしか指定できないといった制約やfilterの例示を書くことによってこのエラーを回避しました。

人間向けのドキュメントを書くのと同じですが、確かにここはより気をつけないといけないなと思った点です。

メタ的な機能を用意する

今回、Cloud Monitoringで利用するためのメトリクスを列挙するための機能を用意しました。 というか、Claude Codeに作ってと言ったら勝手に作ってくれました。

listAvailableMetricsTool := mcp.NewTool("list_available_metrics",
    mcp.WithDescription("List available metrics in Cloud Monitoring"),
    ...

実際にClaude Codeなどで「Cloud Monitoringの機能を利用してDBのコネクション数に異常が無いかを調べてくれ」と依頼したところ、list_available_metricsを利用してどのメトリクスを利用して時系列データを調べるかをリストアップしていました。 これによって僕が知らないメトリクスを利用したりなどしていたので、このようなメタ的な機能を実装するのは重要だと言えそうです。

MCPサーバーとして利用編

今回はAI・機械学習チームで実際に利用している推薦サーバーを対象としてMCPサーバーを利用することにしました。 このサーバーの特徴としては複数のアルゴリズムをバッチ処理で計算を行い、ユーザーからのリクエスト時にアンサンブルしてレスポンスを返すようなサーバーになっています。 データ自体はCloud SQL for MySQLに格納しています。

Claudeで利用する場合には次のように設定をすることで利用しました。

go install github.com/kitagry/gcp-telemetry-mcp@latest
claude mcp add-json gcp-telemetry-mcp '{ "transportType":"stdio", "command":"gcp-telemetry-mcp", "env": {"GOOGLE_CLOUD_PROJECT": "YOUR_GOOGLE_CLOUD_PROJECT" }}'

お題 インデックス付け忘れ

お題として開発環境でDBのインデックスを外して見ることにしました。 インデックスを外した状態でいくつかのリクエストを投げてみます。 そうすると、次のように1つのクエリだけ時間がかかってしまっています。 このクエリがボトルネックになり全体の速度が低下しています。

インデックスを外したテーブルへのリクエストが遅くなっている図

Claude Codeに聞いてみる

最初は「このエンドポイントのボトルネックを調べて」のような抽象的な質問にしていましたが、それだとMCPサーバーを利用してくれませんでした。 結局ソースコードだけを見て推論しようとします。 それだと、今回のようなコード上には現れないボトルネックを探すのは難しいです。 そこで「Cloud Traceを見て、ボトルネックを調べて」のように方法まで誘導する必要がありました。 この辺もCLAUDE.mdなどのプロンプトを用意して、最初にテレメトリーデータを見るように誘導したいですね。

実際にCloud Traceを使うように指示すれば次のように見てくれました。

Traceデータを検索して各Spanの情報を見ている図

Cloud Traceからボトルネックを発見し、改善策を考える図

実際にTraceをいくつか検索し、各Spanを見ています。 どのテーブルへのリクエストが遅いかまで確実に発見していますね。 また、どのカラムへインデックスを貼れば良いかまでちゃんと指示出来ています。 このくらいであれば人間が見れば一瞬で解決できそうですが、Claude Codeを利用したほうが解決策に至るまでが早い気がしました。

まとめ

DBへのインデックス貼り忘れのような原因が明らかな場合はClaude Codeでもすぐに解決策を出してくれることがわかりました。 しかし、方法を明らかにしない場合にはソースコードのみから探索したりなど、筋の悪い探索方法になってしまいました。 この問題を解決するには人間がある程度調査方法にあたりを付けて適切に指示する必要がありそうです。 個人的にはAIの能力は利用する人間の能力にキャップされると思っています。 今回も僕自身が解決出来ない問題については解けないのではないかと思っています。 逆に僕自身が素早く原因を探せそうな問題については、僕よりも高速に解決策までたどり着いてくれました。

今後の自分のスタイルとしては関係がありそうなテレメトリーデータの列挙や特徴の抽出はClaude Codeにしてもらい、人間は列挙された中から関係ありそうなものを選択するといった人間とAIの共同作業をしていくスタイルにしてみようと思います(小並感)。 まだまだ人間のやることはあるので精進していこうと思います。

We are hiring

このようにAI時代においても人の能力はまだまだ重要だと実感していますし、まだまだ仲間を募集しています! カジュアル面談なども募集しているのでまず話してみたいという方も是非。

エンジニア採用ページはこちら

jobs.m3.com

カジュアル面談もお気軽にどうぞ

jobs.m3.com

インターンも常時募集しています

open.talentio.com