このクイック スタートでは、Azure Developer CLI (azd) を使用して、テンプレート プロジェクトからカスタム リモート モデル コンテキスト プロトコル (MCP) サーバーを作成します。 MCP サーバーは、Azure Functions MCP サーバー拡張機能を使用して、AI モデル、エージェント、アシスタント用のツールを提供します。 プロジェクトをローカルで実行し、GitHub Copilot を使用してコードを検証した後、セキュリティで保護されたスケーラブルなデプロイに関する現在のベスト プラクティスに従って、Azure Functions の新しいサーバーレス関数アプリにデプロイします。
ヒント
Functions を使用すると、コード プロジェクトに変更を加えることなく、既存の MCP サーバー コード プロジェクトを Flex Consumption プラン アプリにデプロイすることもできます。 詳細については、「 クイック スタート: Azure Functions で既存の MCP サーバーをホストする」を参照してください。
新しいアプリは、 従量課金 制の課金モデルに従う Flex Consumption プランで実行されるため、このクイックスタートを完了すると、Azure アカウントで数 USD セント以下の小さなコストが発生します。
Important
カスタム MCP サーバーの作成はすべての Functions 言語でサポートされていますが、このクイック スタート シナリオには現在、C#、Python、TypeScript の例しかありません。 このクイック スタートを完了するには、この記事の上部にあるサポートされている言語のいずれかを選択します。
この記事は、Azure Functions の Node.js プログラミング モデルのバージョン 4 に対応しています。
この記事は、Azure Functions の Python プログラミング モデルのバージョン 2 に対応しています。
[前提条件]
-
Java 17 Developer Kit
- 別のサポートされているバージョンの Java を使用する場合は、プロジェクトの pom.xml ファイルを更新する必要があります。
-
JAVA_HOME環境変数を、Java Development Kit (JDK) の正しいバージョンのインストール場所に設定します。
- Apache Maven 3.8.x
Visual Studio Code と次の拡張機能:
Azure Functions 拡張機能。 この拡張機能には Azure Functions Core Tools が 必要であり、使用できない場合はインストールを試みます。
Azure CLI。 Azure Cloud Shell で Azure CLI コマンドを実行することもできます。
アクティブなサブスクリプションを持つ Azure アカウント。 無料でアカウントを作成できます。
プロジェクトを初期化する
azd init コマンドを使用して、テンプレートからローカル Azure Functions コード プロジェクトを作成します。
- Visual Studio Code で、プロジェクトを作成するフォルダーまたはワークスペースを開きます。
ターミナルで、次の
azd initコマンドを実行します。azd init --template remote-mcp-functions-dotnet -e mcpserver-dotnetこのコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。
-eフラグでは、現在の環境の名前が設定されます。azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソース グループの名前でも使用されます。
ローカル ターミナルまたはコマンド プロンプトで、次の
azd initコマンドを実行します。azd init --template remote-mcp-functions-java -e mcpserver-javaこのコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。
-eフラグでは、現在の環境の名前が設定されます。azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。
ローカル ターミナルまたはコマンド プロンプトで、次の
azd initコマンドを実行します。azd init --template remote-mcp-functions-typescript -e mcpserver-tsこのコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。
-eフラグでは、現在の環境の名前が設定されます。azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。
ローカル ターミナルまたはコマンド プロンプトで、次の
azd initコマンドを実行します。azd init --template remote-mcp-functions-python -e mcpserver-pythonこのコマンドにより、テンプレート リポジトリからプロジェクト ファイルがプルされ、現在のフォルダー内のプロジェクトが初期化されます。
-eフラグでは、現在の環境の名前が設定されます。azdでは、環境はアプリの一意のデプロイ コンテキストを維持し、複数を定義できます。 これは、Azure で作成するリソースの名前でも使用されます。
ストレージ エミュレーターを起動する
Azurite エミュレーターを使用して、コード プロジェクトをローカルで実行するときに Azure Storage アカウント接続をシミュレートします。
まだインストールしていない場合は、 Azurite をインストールします。
F1 キーを押します。 コマンド パレットで、コマンド
Azurite: Startを検索して実行し、ローカル ストレージ エミュレーターを起動します。
MCP サーバーをローカルで実行する
Visual Studio Code は Azure Functions Core ツール と統合され、Azurite エミュレーターを使用してローカル開発コンピューターでこのプロジェクトを実行できます。
関数をローカルで開始するには、F5 キーまたは、左側のアクティビティ バーの [実行とデバッグ] アイコンを押します。 ターミナル パネルに、Core Tools からの出力が表示されます。 アプリは ターミナル パネルで起動し、ローカルで実行されている関数の名前を確認できます。
Visual Studio Code で GitHub Copilot を構成するために使用するローカル MCP サーバー エンドポイント (
http://localhost:7071/runtime/webhooks/mcpなど) をメモしておきます。
GitHub Copilot を使用して確認する
コードを確認するには、実行中のプロジェクトを Visual Studio Code の GitHub Copilot の MCP サーバーとして追加します。
F1 キーを押します。 コマンド パレットで、 MCP: Add Server を検索して実行します。
トランスポートの種類として HTTP (Server-Sent イベント) を選択します。
前の手順でコピーした MCP エンドポイントの URL を入力します。
生成された サーバー ID を 使用し、[ ワークスペース ] を選択して、MCP サーバー接続をワークスペース設定に保存します。
コマンド パレットを開き、 MCP: List Servers を 実行し、追加したサーバーが一覧表示されて実行されていることを確認します。
Copilot チャットで、[ エージェント モード] を選択し、次のプロンプトを実行します。
Say Helloツールの実行を求められたら、 このワークスペースで [許可 ] を選択して、アクセス許可を付与し続ける必要がないようにします。 プロンプトが実行され、
Hello World応答が返され、関数の実行情報がログに書き込まれます。次に、いずれかのプロジェクト ファイルでコードを選択し、次のプロンプトを実行します。
Save this snippet as snippet1Copilot はスニペットを格納し、
getSnippetsツールを使用してスニペットを取得する方法に関する情報を要求に応答します。 ここでも、ログで関数の実行を確認し、saveSnippets関数が実行されたことを確認できます。Copilot チャットで、次のプロンプトを実行します。
Retrieve snippet1 and apply to NewFileCopilot はスニペットを取得し、
NewFileという名前のファイルに追加し、コード スニペットをプロジェクトで動作させるために必要と思われる他の操作を行います。 Functions ログには、getSnippetsエンドポイントが呼び出されたことが示されます。テストが完了したら、Ctrl キーを押しながら C キーを押して Functions ホストを停止します。
コードの確認 (省略可能)
MCP サーバー ツールを定義するコードを確認できます。
MCP サーバー ツールの関数コードは、 src フォルダーに定義されています。
McpToolTrigger属性は、MCP サーバー ツールとして関数を公開します。
[Function(nameof(SayHello))]
public string SayHello(
[McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
logger.LogInformation("Saying hello");
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 サーバー ツールとして関数を公開します。
description = "The messages to be logged.",
isRequired = true,
isArray = true)
String messages,
final ExecutionContext functionExecutionContext
) {
functionExecutionContext.getLogger().info("Hello, World!");
functionExecutionContext.getLogger().info("Tool Name: " + mcpToolInvocationContext.getName());
functionExecutionContext.getLogger().info("Transport Type: " + mcpToolInvocationContext.getTransportType());
// Handle different transport types
if (mcpToolInvocationContext.isHttpStreamable()) {
functionExecutionContext.getLogger().info("Session ID: " + mcpToolInvocationContext.getSessionid());
} else if (mcpToolInvocationContext.isHttpSse()) {
if (mcpToolInvocationContext.getClientinfo() != null) {
functionExecutionContext.getLogger().info("Client: " +
mcpToolInvocationContext.getClientinfo().get("name").getAsString() + " v" +
// Write the snippet content to the output blob
outputBlob.setValue(snippet);
return "Successfully saved snippet '" + snippetName + "' with " + snippet.length() + " characters.";
}
/**
* Azure Function that handles retrieving a text snippet from Azure Blob Storage.
* <p>
* The function is triggered by an MCP Tool Trigger. The snippet name is provided
* as an MCP tool property, and the snippet content is read from the blob at the
* path derived from the snippet name.
*
* @param mcpToolInvocationContext The JSON input from the MCP tool trigger.
* @param snippetName The name of the snippet to retrieve, provided as an MCP tool property.
* @param inputBlob The Azure Blob input binding that fetches the snippet content.
* @param functionExecutionContext The execution context for logging.
*/
@FunctionName("GetSnippets")
@StorageAccount("AzureWebJobsStorage")
public String getSnippet(
@McpToolTrigger(
name = "getSnippets",
description = "Gets a text snippet from your snippets collection.")
String mcpToolInvocationContext,
@McpToolProperty(
name = SNIPPET_NAME_PROPERTY_NAME,
propertyType = "string",
description = "The name of the snippet.",
isRequired = true)
String snippetName,
@BlobInput(name = "inputBlob", path = BLOB_PATH)
String inputBlob,
final ExecutionContext functionExecutionContext
) {
// Log the entire incoming JSON for debugging
functionExecutionContext.getLogger().info(mcpToolInvocationContext);
// Log the snippet name and the fetched snippet content from the blob
完全なプロジェクト テンプレートは 、Azure Functions Java MCP Server GitHub リポジトリで確認できます。
MCP サーバー ツールの関数コードは、 src/function_app.py ファイルで定義されています。 MCP 関数の注釈は、次の関数を MCP サーバー ツールとして公開します。
tool_properties_save_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_save_snippets_object])
tool_properties_get_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_get_snippets_object])
@app.generic_trigger(
arg_name="context",
type="mcpToolTrigger",
toolName="hello_mcp",
description="Hello world.",
toolProperties="[]",
)
def hello_mcp(context) -> None:
"""
@app.generic_trigger(
arg_name="context",
type="mcpToolTrigger",
toolName="save_snippet",
description="Save a snippet with a name.",
toolProperties=tool_properties_save_snippets_json,
)
@app.generic_output_binding(arg_name="file", type="blob", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def save_snippet(file: func.Out[str], context) -> str:
content = json.loads(context)
snippet_name_from_args = content["arguments"][_SNIPPET_NAME_PROPERTY_NAME]
snippet_content_from_args = content["arguments"][_SNIPPET_PROPERTY_NAME]
if not snippet_name_from_args:
return "No snippet name provided"
if not snippet_content_from_args:
return "No snippet content provided"
file.set(snippet_content_from_args)
logging.info(f"Saved snippet: {snippet_content_from_args}")
return f"Snippet '{snippet_content_from_args}' saved successfully"
完全なプロジェクト テンプレートは 、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 up コマンドを使用して、Azure の Flex 従量課金プランの新しい関数アプリにこのプロジェクトをデプロイするように構成されています。 このプロジェクトには、ベスト プラクティスに従った Flex 消費プランへのセキュアなデプロイメントの作成に使用する Bicep ファイルのセットが含まれています。
Visual Studio Code で、F1 キーを押してコマンド パレットを開きます。 コマンド
Azure Developer CLI (azd): Package, Provison and Deploy (up)を検索して実行します。 次に、Azure アカウントを使用してサインインします。まだサインインしていない場合は、Azure アカウントで認証します。
プロンプトが表示されたら、次の必須のデプロイ パラメーターを指定します。
パラメーター Description Azure サブスクリプション リソースが作成されるサブスクリプション。 Azure の場所 新しい Azure リソースを含むリソース グループを作成する Azure リージョン。 現在、Flex 従量課金プランをサポートしているリージョンのみが表示されます。 コマンドが正常に完了した後、作成したリソースへのリンクが表示されます。
リモート MCP サーバーに接続する
これで、MCP サーバーが Azure で実行されています。 ツールにアクセスするときは、要求にシステム キーを含める必要があります。 このキーは、リモート MCP サーバーにアクセスするクライアントに対して、ある程度のアクセス制御を提供します。 このキーを取得したら、GitHub Copilot をリモート サーバーに接続できます。
azdと Azure CLI を使用して、ツールにアクセスするために必要な MCP サーバー URL とシステム キー (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 "MCP Server URL: %s\n" "https://$SERVICE_API_NAME.azurewebsites.net/runtime/webhooks/mcp" printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY"Visual Studio Code で F1 キーを押してコマンド パレットを開き、コマンド
MCP: Open Workspace Folder MCP Configuratonを検索して実行すると、mcp.json構成ファイルが開きます。mcp.json構成で、前に追加した名前付き MCP サーバーを見つけ、urlの値をリモート MCP サーバー URL に変更し、次の例のように、コピーした MCP サーバー アクセス キーを含むheaders.x-functions-key要素を追加します。{ "servers": { "remote-mcp-function": { "type": "http", "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp", "headers": { "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..." } } } }開いているでサーバー名の上にある
mcp.json] ボタンを選択して、リモート MCP サーバーを再起動します。今回は、デプロイしたアプリを使用します。
デプロイメントを検証する
ローカルで行ったのと同じように GitHub Copilot でリモート MCP ツールを使用できるようになりましたが、Azure でコードが安全に実行されるようになりました。 前に使用したのと同じコマンドを再生して、すべてが正しく動作することを確認します。
リソースをクリーンアップする
MCP サーバーと関連リソースの操作が完了したら、次のコマンドを使用して関数アプリとその関連リソースを Azure から削除し、さらにコストが発生しないようにします。
azd down --no-prompt
注
--no-prompt オプションは、確認なしでリソース グループを削除するようにazdに指示します。 このコマンドは、ローカル コード プロジェクトには影響しません。