はじめに
これまでの投稿で、OpenAI の Function Calling や OCI Generative AI Service の Cohere Tool Use を使って Oracle Cloud Infrastructure のメトリクスを自然言語で問い合わせてみましたが、昨今の MCP の盛り上がりを受けての第三弾をやってみようかな?... ということで。
今回は、FastMCP を使って OCI のメトリクスを取得する部分を MCP Server として実装し、LangChain や Cline から呼び出してみます。
FastMCP は MCP Server & Client をサクッと作れる Python のパッケージです。
Cline は本来 VS Code の拡張機能として動作する AI 搭載コーディング支援ツールですが、MCP Server と連携できるため、Chat のフロントエンド的に使ってみます。
これまでの投稿で実装した方式は、ツールの呼び出しが OpenAI や Cohere の世界に縛られていた訳ですが、今回は MCP というニュートラルなプロトコルが介在するお陰で、MCP Client/Host や制御する LLM モデルに制約がなくなっていて、このあたりがちょっと趣の違うところです。
事前準備
FastMCP を pip でインストール
pip install fastmcp
LangChain / Cline で使用するモデルは任意ですが、今回は gemini-2.5-pro (無料枠の Gemini API) を使いました。
MCP Server を作成する
関数部分はこれまでの投稿のソースとほぼ同じです。@mcp.tool()
というデコレータを使っています。
関数の説明を全てコメントの部分で行なっているのがちょっと違うところかな?
""" compute-metrics.py """
from fastmcp import FastMCP
import oci, os, json
from datetime import datetime, timedelta, timezone
# Create an MCP server
mcp = FastMCP("ComputeMetrics")
@mcp.tool()
def get_metrics(metric_type: str, inequality_sign: str = None, boundary_value: float = None):
"""
コンピュートのメトリクス (cpu or memory) を取得する関数
直近1分間の utilization 平均値 1レコードを取得する
description:
Get resource metrics retrieved by agents in compute instances.
It returns 'displayName', 'timestamp' and 'value' for each resource.
'displayName' is a name of compute instances. It must be displayed as is, and it must not be translated to other languages.
'value' is always expressed as percentage, hence if 'value' is 0.2, it is not '20%' but '0.2%'. " +
The type of metrics is either cpu or memory. 'displayName' cannot be translated into any language.
parameters:
- metric_type : The type of the resource metrics. it must be either 'cpu' or 'memory'.
- inequality_sign : The condition to filter values, it can be ommited when you want to get metrics of all resources.
The value must be one of 'gt', 'ge', 'le', 'lt'.
'以上' は 'ge' で表現され、'以下' は 'le' で表現されます。
- boundary_value : The value to filter, expressed as percentage.
"""
# 検索カテゴリーは "cpu" か "memory" のいずれか、1分間の平均使用率
metric_types = {
"cpu" : "CPUUtilization[1m].mean()",
"memory" : "MemoryUtilization[1m].mean()"
}
query = metric_types[metric_type.lower()]
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
config = {'region': signer.region, 'tenancy': signer.tenancy_id}
metric_client = oci.monitoring.MonitoringClient(config, signer=signer)
metric_detail = oci.monitoring.models.SummarizeMetricsDataDetails()
metric_detail.query = query
# とりあえず最新のデータだけを取得する仕様にする
now = datetime.now(tz=timezone.utc)
metric_detail.start_time = (now - timedelta(minutes=1)).isoformat()
metric_detail.end_time = now.isoformat()
metric_detail.resolution = "1m"
metric_detail.namespace = "oci_computeagent"
compartment_id = os.getenv("COMPARTMENT_ID")
metrics = metric_client.summarize_metrics_data(compartment_id, metric_detail).data
results = []
for m in metrics:
timestamp = m.aggregated_datapoints[0].timestamp
value = m.aggregated_datapoints[0].value
resourceDisplayName = m.dimensions["resourceDisplayName"]
if not inequality_sign or \
(inequality_sign.lower() == "gt" and value > boundary_value) or \
(inequality_sign.lower() == "ge" and value >= boundary_value) or \
(inequality_sign.lower() == "le" and value <= boundary_value) or \
(inequality_sign.lower() == "lt" and value < boundary_value) :
results.append({
"displayName" : resourceDisplayName,
"timestamp" : timestamp.isoformat(),
"value" : value
})
print(f">>> results\n{json.dumps(results, indent=2)}\n<<<")
return {"query" : query, "metrics" : results}
if __name__ == "__main__":
mcp.run(transport="stdio")
#mcp.run(transport="http", host="127.0.0.1", port=8000, path="/mcp")
#mcp.run(transport="sse", host="127.0.0.1", port=8000)
関数の実装以外ほとんどコーディングすることなく MCP Server が出来上がりました。
最後にコメントアウトしているところがありますが、これは MCP Server の起動モードのオプションを示しています。今回は、stdio
モード、標準入出力がパイプで繋がっている状態で Client と通信します。
では、これから MCP Server をいろいろな方法で呼び出してみましょう。
MCP Client から MCP Server を呼び出す
まず最初に MCP Client を作って Server を呼び出してみましょう。
""" compute-metrics-client.py """
import asyncio, os, json, types
from fastmcp import Client
from fastmcp.client.transports import PythonStdioTransport
from fastmcp.client.client import CallToolResult
from mcp.types import Tool
async def main(metric_type, inequality_sign, boundary_value):
# stdio - MCP Server を子プロセスとして起動して、標準入出力をパイプで繋ぐ
server_script = "compute-metrics.py"
env = {"COMPARTMENT_ID" : os.getenv("COMPARTMENT_ID")} # 環境変数を子プロセスに渡す
transport = PythonStdioTransport(script_path=server_script, env=env)
# クライアントを作成してサーバと通信
async with Client(transport) as client:
# tool をリストする
tools = await client.list_tools() # type: types.List[Tool]
print(f"Tools: {tools}")
# tool を呼び出す
result = await client.call_tool("get_metrics",
{
"metric_type": metric_type,
"inequality_sign": inequality_sign,
"boundary_value": boundary_value
}
) # type: CallToolResult
print(f"\nResult(content):")
print(json.dumps(json.loads(result.content[0].text), indent=2))
if __name__ == "__main__":
# メモリーの使用率が25%以上のインスタンスを調べる
asyncio.run(main("memory", "ge", 25))
では、このスクリプトを実行します。
$ python compute-metrics-client.py
╭─ FastMCP 2.0 ──────────────────────────────────────────────────────────────╮
│ │
│ _ __ ___ ______ __ __ _____________ ____ ____ │
│ _ __ ___ / ____/___ ______/ /_/ |/ / ____/ __ \ |___ \ / __ \ │
│ _ __ ___ / /_ / __ `/ ___/ __/ /|_/ / / / /_/ / ___/ / / / / / │
│ _ __ ___ / __/ / /_/ (__ ) /_/ / / / /___/ ____/ / __/_/ /_/ / │
│ _ __ ___ /_/ \__,_/____/\__/_/ /_/\____/_/ /_____(_)____/ │
│ │
│ │
│ │
│ 🖥️ Server name: ComputeMetrics │
│ 📦 Transport: STDIO │
│ │
│ 📚 Docs: https://gofastmcp.com │
│ 🚀 Deploy: https://fastmcp.cloud │
│ │
│ 🏎️ FastMCP version: 2.10.6 │
│ 🤝 MCP version: 1.12.0 │
│ │
╰────────────────────────────────────────────────────────────────────────────╯
[07/21/25 05:00:25] INFO Starting MCP server 'ComputeMetrics' with transport 'stdio' server.py:1371
Tools: [Tool(name='get_metrics', title=None, description='コンピュートのメトリクス (cpu or memory) を取得する関数\n直近1分間の utilization 平均値 1レコードを取得する\n\ndescription:\nGet resource metrics retrieved by agents in compute instances.\nIt returns \'displayName\', \'timestamp\' and \'value\' for each resource.\n\'displayName\' is a name of compute instances. It must be displayed as is, and it must not be translated to other languages.\n\'value\' is always expressed as percentage, hence if \'value\' is 0.2, it is not \'20%\' but \'0.2%\'. " +\nThe type of metrics is either cpu or memory. \'displayName\' cannot be translated into any language.\n\nparameters:\n - metric_type : The type of the resource metrics. it must be either \'cpu\' or \'memory\'.\n - inequality_sign : The condition to filter values, it can be ommited when you want to get metrics of all resources.\n The value must be one of \'gt\', \'ge\', \'le\', \'lt\'.\n \'以上\' は \'ge\' で表現され、\'以下\' は \'le\' で表現されます。\n - boundary_value : The value to filter, expressed as percentage.', inputSchema={'properties': {'metric_type': {'title': 'Metric Type', 'type': 'string'}, 'inequality_sign': {'default': None, 'title': 'Inequality Sign', 'type': 'string'}, 'boundary_value': {'default': None, 'title': 'Boundary Value', 'type': 'number'}}, 'required': ['metric_type'], 'type': 'object'}, outputSchema=None, annotations=None, meta=None)]
Result(content):
{
"query": "MemoryUtilization[1m].mean()",
"metrics": [
{
"displayName": "puppy",
"timestamp": "2025-07-21T05:00:00+00:00",
"value": 32.558806877053996
},
{
"displayName": "coala",
"timestamp": "2025-07-21T05:00:00+00:00",
"value": 29.094438360059286
}
]
}
出力がちょっと見にくいですが、ツールの名前、詳細、入出力スキーマ等の情報が表示され、次に実行結果として「メモリーの使用率が25%以上のインスタンス」の検索結果が表示されています。
ここでは MCP Client に渡す入力パラメータをベタにコーディングしていますが、これから試す LangChain や Cline では、自然言語による問い合わせから LLM を使ってパラメータの値を導出します。
LangChain から MCP Server を呼び出す
次に LangChain から呼び出してみましょう。
LLM は gemini-2.5-pro を使います。
必要なパッケージの導入
pip install langchain-mcp-adapters langgraph langchain-google-genai
export GOOGLE_API_KEY=<your_api_key>
以下のスクリプトでは MCP Client 経由で Tool をロードして Agent を作成し、最後に問い合わせを実行して結果を表示しています。
""" compute-metrics-langchain.py """
import asyncio, os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_core.messages import AIMessage
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_google_genai import ChatGoogleGenerativeAI
async def main(query):
# stdio モード
server_params = StdioServerParameters(
command="<your python home>/bin/python",
args=["compute-metrics.py"],
env={"COMPARTMENT_ID" : os.getenv("COMPARTMENT_ID")}
)
# MCP Client を作成して MCP Server と通信
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the connection
await session.initialize()
# Get tools
tools = await load_mcp_tools(session)
# Create and run the agent
llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro")
agent = create_react_agent(llm, tools)
agent_response = await agent.ainvoke({"messages": query})
print(agent_response["messages"][-1].content)
if __name__ == "__main__":
query = "メモリーの使用率が25%以上のインスタンスは?"
asyncio.run(main(query))
実行結果は以下の通り。
$ python compute-metrics-langchain.py
╭─ FastMCP 2.0 ──────────────────────────────────────────────────────────────╮
│ │
│ _ __ ___ ______ __ __ _____________ ____ ____ │
│ _ __ ___ / ____/___ ______/ /_/ |/ / ____/ __ \ |___ \ / __ \ │
│ _ __ ___ / /_ / __ `/ ___/ __/ /|_/ / / / /_/ / ___/ / / / / / │
│ _ __ ___ / __/ / /_/ (__ ) /_/ / / / /___/ ____/ / __/_/ /_/ / │
│ _ __ ___ /_/ \__,_/____/\__/_/ /_/\____/_/ /_____(_)____/ │
│ │
│ │
│ │
│ 🖥️ Server name: ComputeMetrics │
│ 📦 Transport: STDIO │
│ │
│ 📚 Docs: https://gofastmcp.com │
│ 🚀 Deploy: https://fastmcp.cloud │
│ │
│ 🏎️ FastMCP version: 2.10.6 │
│ 🤝 MCP version: 1.12.0 │
│ │
╰────────────────────────────────────────────────────────────────────────────╯
[07/21/25 02:15:55] INFO Starting MCP server 'ComputeMetrics' with transport 'stdio' server.py:1371
メモリー使用率が25%以上のインスタンスは、puppy (33.28%) と coala (28.74%) です。
Cline から MCP Server を呼び出す
では、ここから Cline から呼び出す手順に入ります。
VS Code に拡張機能 Cline をインストールしたのち、Cline のペインの上部にある「MCP Servers」をクリックします。
「Installed」のタブから「Configure MCP Servers」をクリックすると、VS Code のエディタが開きます。cline_mcp_settings.json
というファイルです。
{
"mcpServers": {
}
}
最初は空っぽの設定ファイルですが、ここに MCP Server を登録します。
{
"mcpServers": {
"compute_metrics": {
"timeout": 60,
"type": "stdio",
"command": "<your python home>/bin/python",
"args": [
"<your project directory>/get-compute-metrics.py"
],
"env": {
"COMPARTMENT_ID": "ocid1.compartment.oc1.."
}
}
}
}
ファイルを保存し、サーバが登録されているのを確認して下さい。
これで、準備完了です。では実際に問い合わせを実行してみましょう。
「メモリーの使用率が25%以上のインスタンスを教えて」を試してみます。
上記のプロンプトを入れて実行してみると以下のような画面になりました。
get_metrics
ツールを、表示されたパラメータで呼び出そうとしています。
「Approve」をクリックして続行します。
ツールの実行結果が表示されて、最終的な回答が得られました。
メモリ使用率が25%以上のインスタンスは次のとおりです。
- puppy: 32.75%
- coala: 29.15%
まとめ
今回は、以下のことをやってみました。
- MCP Server を作成する
- MCP Client から MCP Server を呼び出す
- LangChain から MCP Server を呼び出す
- Cline から MCP Server を呼び出す
MCP の登場によって、"Agent" の可能性がものすごく広がりましたね ☺️