次の方法で共有


クイック スタート: Azure Functions を使用してカスタム リモート MCP サーバーを構築する

このクイック スタートでは、Azure Developer CLI (azd) を使用して、テンプレート プロジェクトからカスタム リモート モデル コンテキスト プロトコル (MCP) サーバーを作成します。 この MCP サーバーは、Azure Functions MCP サーバー拡張機能を使用して、AI モデル、エージェント、アシスタント用のツールを提供します。 MCP サーバー拡張機能を使用して 、対話型の MCP アプリを作成することもできます。

プロジェクトをローカルで実行し、GitHub Copilot を使用してコードを検証した後、セキュリティで保護されたスケーラブルなデプロイに関する現在のベスト プラクティスに従って、Azure Functions の新しいサーバーレス関数アプリにデプロイします。

新しいアプリは、 従量課金 制の課金モデルに従う Flex Consumption プランで実行されるため、このクイックスタートを完了すると、Azure アカウントで数 USD セント以下の小さなコストが発生します。

Important

カスタム MCP サーバーの作成はすべての Functions 言語でサポートされていますが、現在、このクイック スタート シナリオには C#、Java、Python、TypeScript の例しかありません。 このクイック スタートを完了するには、この記事の上部にあるサポートされている言語のいずれかを選択します。

この記事は、Azure Functions の Node.js プログラミング モデルのバージョン 4 に対応しています。

この記事は、Azure Functions の Python プログラミング モデルのバージョン 2 に対応しています。

[前提条件]

プロジェクトを初期化する

azd init コマンドを使用して、テンプレートからローカル Azure Functions コード プロジェクトを作成します。

  1. Visual Studio Code で、プロジェクトを作成するフォルダーまたはワークスペースを開きます。
  1. ターミナルで、次の azd init コマンドを実行します。

    azd init --template remote-mcp-functions-dotnet -e mcpserver-dotnet
    

    このコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。 -e フラグでは、現在の環境の名前が設定されます。 azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソース グループの名前でも使用されます。

  1. ローカル ターミナルまたはコマンド プロンプトで、次の azd init コマンドを実行します。

    azd init --template remote-mcp-functions-java -e mcpserver-java 
    

    このコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。 -e フラグでは、現在の環境の名前が設定されます。 azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。

  1. ローカル ターミナルまたはコマンド プロンプトで、次の azd init コマンドを実行します。

    azd init --template remote-mcp-functions-typescript -e mcpserver-ts
    

    このコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。 -e フラグでは、現在の環境の名前が設定されます。 azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。

  1. ローカル ターミナルまたはコマンド プロンプトで、次の azd init コマンドを実行します。

    azd init --template remote-mcp-functions-python -e mcpserver-python
    

    このコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。 -e フラグでは、現在の環境の名前が設定されます。 azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。

ストレージ エミュレーターを起動する

Azurite エミュレーターを使用して、コード プロジェクトをローカルで実行するときに Azure Storage アカウント接続をシミュレートします。

  1. まだインストールしていない場合は、 Azurite をインストールします。

  2. F1 キーを押します。 コマンド パレットで、コマンド Azurite: Start を検索して実行し、ローカル ストレージ エミュレーターを起動します。

MCP サーバーをローカルで実行する

ターミナル ウィンドウで、 FunctionsMcpTool プロジェクト フォルダーに移動します。

cd src/FunctionsMcpTool

Visual Studio Code は Azure Functions Core ツール と統合され、ローカル開発コンピューターでこのプロジェクトを実行できます。 Functions アプリをローカルで起動するには、 F5 キーを押すか、左側のアクティビティ バーの [実行とデバッグ ] アイコンを選択します。

ターミナル パネルに、Core Tools からの出力が表示されます。 アプリは ターミナル パネルで起動し、ローカルで実行されている関数の名前を確認できます。

GitHub Copilot を使用して確認する

プロジェクト テンプレートには、ローカル MCP エンドポイントを指す.vscode/mcp.json サーバーを既に定義しているlocal-mcp-function ファイルが含まれています。 Visual Studio Code で GitHub Copilot を使用してコードを確認するには、次の構成を使用します。

  1. .vscode/mcp.json ファイルを開き、構成の上にある local-mcp-function ボタンを選択します。

  2. [Copilot チャット ] ウィンドウで、 エージェント モードが選択されていることを確認し、[ツールの 構成 ] アイコンを選択して、チャットで MCP Server:local-mcp-function が有効になっていることを確認します。

  3. このプロンプトを実行します。

    Say Hello
    

    ツールの実行を求められたら、 このワークスペースで [許可 ] を選択して、アクセス許可を付与し続ける必要がないようにします。 プロンプトが実行され、 Hello World 応答が返され、関数の実行情報がログに書き込まれます。

  4. 次に、いずれかのプロジェクト ファイルでコードを選択し、次のプロンプトを実行します。

    Save this snippet as snippet1
    

    Copilot はスニペットを格納し、 getSnippets ツールを使用してスニペットを取得する方法に関する情報を要求に応答します。 ここでも、ログで関数の実行を確認し、 saveSnippets 関数が実行されたことを確認できます。

  5. Copilot チャットで、次のプロンプトを実行します。

    Retrieve snippet1 and apply to NewFile
    

    Copilot はスニペットを取得し、 NewFileという名前のファイルに追加し、コード スニペットをプロジェクトで動作させるために必要と思われる他の操作を行います。 Functions ログには、 getSnippets エンドポイントが呼び出されたことが示されます。

  6. テストが完了したら、Ctrl キーを押しながら C キーを押して Functions ホストを停止します。

コードの確認 (省略可能)

MCP サーバー ツールを定義するコードを確認できます。

MCP サーバー ツールの関数コードは、 src フォルダーに定義されています。 McpToolTrigger属性は、MCP サーバー ツールとして関数を公開します。

[Function(nameof(SayHello))]
public string SayHello(
    [McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
    logger.LogInformation("C# MCP tool trigger function processed a request.");
    return "Hello I am MCP Tool!";
}
    [Function(nameof(GetSnippet))]
    public object GetSnippet(
        [McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)]
            ToolInvocationContext context,
        [BlobInput(BlobPath)] string snippetContent
    )
    {
        return snippetContent;
    }

    [Function(nameof(SaveSnippet))]
    [BlobOutput(BlobPath)]
    public string SaveSnippet(
        [McpToolTrigger(SaveSnippetToolName, SaveSnippetToolDescription)]
            ToolInvocationContext context,
        [McpToolProperty(SnippetNamePropertyName, SnippetNamePropertyDescription, true)]
            string name,
        [McpToolProperty(SnippetPropertyName, SnippetPropertyDescription, true)]
            string snippet
    )
    {
        return snippet;
    }
}

完全なプロジェクト テンプレートは 、Azure Functions .NET MCP Server GitHub リポジトリで確認できます。

MCP サーバー ツールの関数コードは、 src/main/java/com/function/ フォルダーに定義されています。 @McpToolTrigger注釈は、MCP サーバー ツールとして関数を公開します。

完全なプロジェクト テンプレートは 、Azure Functions Java MCP Server GitHub リポジトリで確認できます。

MCP サーバー ツールの関数コードは、 src/function_app.py ファイルで定義されています。 MCP 関数の注釈は、次の関数を MCP サーバー ツールとして公開します。


@app.mcp_tool()
def hello_mcp() -> str:
    """Hello world."""

@app.mcp_tool()
@app.mcp_tool_property(arg_name="snippetname", description="The name of the snippet.")
@app.blob_input(arg_name="file", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def get_snippet(file: func.InputStream, snippetname: str) -> str:
    """Retrieve a snippet by name from Azure Blob Storage."""
    snippet_content = file.read().decode("utf-8")
    logging.info(f"Retrieved snippet: {snippet_content}")
    return snippet_content


@app.mcp_tool()
@app.mcp_tool_property(arg_name="snippetname", description="The name of the snippet.")
@app.mcp_tool_property(arg_name="snippet", description="The content of the snippet.")
@app.blob_output(arg_name="file", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def save_snippet(file: func.Out[str], snippetname: str, snippet: str) -> str:
    """Save a snippet with a name to Azure Blob Storage."""
    if not snippetname:
        return "No snippet name provided"

    if not snippet:
        return "No snippet content provided"

    file.set(snippet)
    logging.info(f"Saved snippet: {snippet}")

完全なプロジェクト テンプレートは 、Azure Functions Python MCP Server GitHub リポジトリで確認できます。

MCP サーバー ツールの関数コードは、 src フォルダーに定義されています。 MCP 関数の登録では、次の関数が MCP サーバー ツールとして公開されます。

export async function mcpToolHello(_toolArguments:unknown, context: InvocationContext): Promise<string> {
    console.log(_toolArguments);
    // Get name from the tool arguments
    const mcptoolargs = context.triggerMetadata.mcptoolargs as {
        name?: string;
    };
    const name = mcptoolargs?.name;

    console.info(`Hello ${name}, I am MCP Tool!`);
    
    return `Hello ${name || 'World'}, I am MCP Tool!`;
}

// Register the hello tool
app.mcpTool('hello', {
    toolName: 'hello',
    description: 'Simple hello world MCP Tool that responses with a hello message.',
    toolProperties:{
        name: arg.string().describe('Required property to identify the caller.').optional()
    },
    handler: mcpToolHello
});
// SaveSnippet function - saves a snippet with a name
export async function saveSnippet(
  _toolArguments: unknown,
  context: InvocationContext
): Promise<string> {
  console.info("Saving snippet");

  // Get snippet name and content from the tool arguments
  const mcptoolargs = context.triggerMetadata.mcptoolargs as {
    snippetname?: string;
    snippet?: string;
  };

  const snippetName = mcptoolargs?.snippetname;
  const snippet = mcptoolargs?.snippet;

  if (!snippetName) {
    return "No snippet name provided";
  }

  if (!snippet) {
    return "No snippet content provided";
  }

  // Save the snippet to blob storage using the output binding
  context.extraOutputs.set(blobOutputBinding, snippet);

  console.info(`Saved snippet: ${snippetName}`);
  return snippet;
}

完全なプロジェクト テンプレートは 、Azure Functions TypeScript MCP Server GitHub リポジトリで確認できます。

MCP サーバー ツールをローカルで確認したら、プロジェクトを Azure に発行できます。

Azure にデプロイ

このプロジェクトは、 azd を使用して、Azure の Flex Consumption プランの新しい関数アプリにこのプロジェクトをデプロイするように構成されています。 このプロジェクトには、ベスト プラクティスに従った Flex Consumption プランへの安全なデプロイを作成するために azd が使用する Bicep ファイルのセットが含まれています。

  1. Visual Studio Code で、F1 キーを押してコマンド パレットを開きます。 コマンド Azure Developer CLI (azd): Package, Provision and Deploy (up)を検索して実行します。 次に、Azure アカウントを使用してサインインします。

  2. メッセージが表示されたら、次の必須のデプロイ パラメーターを選択します。

    パラメーター Description
    Azure サブスクリプション リソースが作成されるサブスクリプション。
    Azure の場所 新しい Azure リソースを含むリソース グループを作成する Azure リージョン。 現在、Flex 従量課金プランをサポートしているリージョンのみが表示されます。
    vnetEnabled False 仮想ネットワーク リソースの作成をスキップすると、デプロイが簡略化されます。

    コマンドが正常に完了した後、作成したリソースへのリンクが表示されます。

リモート MCP サーバーに接続する

これで、MCP サーバーが Azure で実行されています。 プロジェクト テンプレートには、リモート サーバーに接続するように既に構成されているremote-mcp-function.vscode/mcp.jsonエントリが含まれています。 このサーバーを起動すると、VS Code によって、リモート MCP エンドポイントへのアクセスに必要な関数アプリ名とシステム キーの入力が求められます。

  1. azdと Azure CLI を使用して、関数アプリ名と、ツールにアクセスするために必要なシステム キー (mcp_extension) の両方を出力する次のスクリプトを実行します。

    eval $(azd env get-values --output dotenv)
    MCP_EXTENSION_KEY=$(az functionapp keys list --resource-group $AZURE_RESOURCE_GROUP \
        --name $AZURE_FUNCTION_NAME --query "systemKeys.mcp_extension" -o tsv)
    printf "Function app name: %s\n" "$SERVICE_API_NAME"
    printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY"
    
  2. .vscode/mcp.jsonで、構成の上にある remote-mcp-function を選択します。

  3. メッセージが表示されたら、前の手順の関数アプリ名とシステム キーの値を入力します。

デプロイメントを検証する

ローカルで行ったのと同じように GitHub Copilot でリモート MCP ツールを使用できるようになりましたが、Azure でコードが安全に実行されるようになりました。 前に使用したのと同じコマンドを再生して、すべてが正しく動作することを確認します。

リソースをクリーンアップする

MCP サーバーと関連リソースの操作が完了したら、次のコマンドを使用して関数アプリとその関連リソースを Azure から削除し、さらにコストが発生しないようにします。

azd down 

次のステップ