🔩

Azure Functionを使用した MCP ツールの構築(引数付き):その2

に公開

第 1 回では、シンプルな hello_mcp Azure 関数を作成し、ローカルでのテスト方法と Azure クラウドへのデプロイ方法について学びました。これは、Microsoft Copilot (MCP) ツールを Azure Functions を使ってどのように実装するかを理解するための良い出発点でした。

今回は、引数を受け取る MCP ツールを実装します — 具体的には、2つの整数を受け取り、その合計を返すツールです。これにより、MCP システムからの構造化された入力を処理する方法や、エラーが発生した際の適切なレスポンスの返し方について学ぶことができます。全てのコードがfunction_app.pyにあります。


🧠 MCP ツールとは?

MCP(Model Context Protocol) ツールは、開発者が自身のカスタムロジックを Copilot 機能付きアプリケーション(例:GitHub Copilot や Visual Studio Code など)に公開できるようにする仕組みです。このツールを通じて、LLM支援型ワークフローに独自のバックエンドロジックを統合することが可能になります。

今回のケースでは、add_integers という名前のツールを作成し、2つの整数を入力として受け取り、それらの和を返します。


🛠️ Azure Functionの構造

mcpToolTrigger バインディングを使用して、関数を MCP ツールとして呼び出せるようにします。この関数は以下のような動作を行います:

  • 2つの整数 (num_anum_b) を受け取る
  • それらを加算する
  • JSON 形式で結果を返す

🔑 定数とプロパティ定義

一貫性と明確さのために、プロパティ名を定数として定義します:

_PROPERTY_A_NAME = "num_a"
_PROPERTY_B_NAME = "num_b"

次に、ツールの期待する入力を説明するためのヘルパークラス ToolProperty を使用します:

class ToolProperty:
    def __init__(self, property_name: str, property_type: str, description: str):
        self.propertyName = property_name
        self.propertyType = property_type
        self.description = description

    def to_dict(self):
        return {
            "propertyName": self.propertyName,
            "propertyType": self.propertyType,
            "description": self.description,
        }

これにより、ツールプロパティのスキーマを正しい JSON 形式で生成できます。

📦 ツールプロパティの定義

次のようにして、期待されるプロパティのリストを定義します:

tool_properties_add_integers_object = [
    ToolProperty(_PROPERTY_A_NAME, "integer", "加算する最初の整数"),
    ToolProperty(_PROPERTY_B_NAME, "integer", "加算する2番目の整数"),
]

tool_properties_add_integers_json = json.dumps(
    [prop.to_dict() for prop in tool_properties_add_integers_object]
)

この JSON は mcpToolTrigger に渡され、MCP システムがどの入力を期待すべきかを知る手がかりになります。


🚀 Azure Functionの実装

メインとなる関数には @app.generic_trigger デコレータを使用します:

@app.generic_trigger(
    arg_name="context",
    type="mcpToolTrigger",
    toolName="add_integers",
    description="2つの整数を加算して合計を返します。",
    toolProperties=tool_properties_add_integers_json,
)
def add_integers_tool(context: str) -> str:
    ...

関数は "arguments" キーを持つ JSON 文字列形式で入力値を受け取ります。

✅ 入力チェック

関数内で以下の確認を行います:

  1. context が有効な JSON かどうか
  2. "arguments" キーが存在するか
  3. num_anum_b が含まれているか
  4. 値を整数に変換できるか(変換エラーのハンドリングも含む)

これらのいずれかの検証に失敗した場合、適切なエラーメッセージを JSON 形式で返します。

➕ 加算処理

すべての入力が検証され、パースされた後:

result = num_a + num_b
return json.dumps({"sum": result})

操作内容をログに出力し、結果を JSON オブジェクトで返します。

⚠️ エラーハンドリング

すべての処理は try-except ブロックで囲まれており、予期しない問題にも対応できます:

except json.JSONDecodeError:
    logging.error(f"Failed to decode JSON from context: {context}")
    return json.dumps({"error": "Invalid JSON format in input context."})
except Exception as e:
    logging.error(f"An unexpected error occurred: {str(e)}")
    return json.dumps({"error": f"An unexpected error occurred: {str(e)}"})

🧪 ローカルでのテスト

ローカルでのやりかたには第1回を参照して下さい。
この関数をローカルでテストするには:

  1. Azure Functions サーバーを起動します:
    source .venv/bin/activate
    func start
    

2. MCP Inspectorの使い方にはこちらこちらを見てください。
関数がトリガーされたことを示すログが表示され、以下のようなレスポンスを受け取るはずです:

☁️ Azure へのデプロイ

ローカルでのテストが終わったら、こちらのやり方でデプロイします。

デプロイ後、関数はその公開 URL 経由でアクセス可能になります。このツールを MCP システムに登録するか、HTTP リクエストで直接呼び出すことが可能です。


🎯 まとめ

この記事では、第 1 回の内容を基盤として、Azure Functions を使用して以下のような MCP ツールを作成しました:

  • 2つの整数入力を受け取る
  • 入力の検証とエラーハンドリングを行う
  • 構造化された JSON レスポンスを返す
  • ローカルでテストし、Azure にデプロイできる

このパターンは、外部 API の呼び出し、ファイル処理、データベースとの統合など、より複雑なロジックに拡張できます。また、Copilot 機能を備えたエクスペリエンスに対して、こうしたツールを提供できるようになります。


📌 次回予告

次回記事では、PostgreSQL サーバー用の MCP ツールを実装する方法について紹介します。これにより、LLM が SQL サーバーの必要な機能にアクセスできるようになります。

乞うご期待!

DXC Lab

Discussion