共用方式為


快速入門:使用 Azure Functions 建置自訂遠端 MCP 伺服器

在本快速入門中,您會使用 Azure 開發人員 CLI (azd) 從範本專案建立自訂遠端模型內容通訊協定 (MCP) 伺服器。 MCP 伺服器會使用 Azure Functions MCP 伺服器延伸模組來提供 AI 模型、代理程式和助理的工具。 在本機執行專案並使用 GitHub Copilot 驗證程式碼之後,您可以將它部署至 Azure Functions 中的新無伺服器函式應用程式,以遵循目前安全且可調整部署的最佳做法。

小提示

Functions 也讓你能將現有的 MCP 伺服器程式碼專案部署到 Flex Consumption 計畫應用程式,而無需對程式碼專案做修改。 欲了解更多資訊,請參閱 快速入門:在 Azure Functions 上架設現有 MCP 伺服器

由於新的應用程式會在彈性取用方案上執行,其遵循按 使用量付費的 計費模型,因此完成本快速入門會在您的 Azure 帳戶中產生幾美分或更少的少量成本。

這很重要

雖然所有函式語言都支援 建立自訂 MCP 伺服器 ,但此快速入門情境目前僅包含 C#、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 伺服器

Visual Studio Code 與 Azure Functions 核心工具 整合,可讓您使用 Azurite 模擬器在本機開發電腦上執行此專案。

  1. 若要在本機啟動函式,請按 F5 或左側 [活動] 列中的 [執行並偵錯] 圖示。 「終端機」面板會顯示「核心工具」的輸出。 您的應用程式會在 「終端機」 面板中啟動,您可以看到在本機執行的函式名稱。

  2. 記下本機 MCP 伺服器端點(例如 http://localhost:7071/runtime/webhooks/mcp),以便在 Visual Studio Code 中配置 GitHub Copilot。

使用 GitHub Copilot 進行驗證

若要驗證您的程式碼,請在 Visual Studio Code 中將執行中的專案新增為 GitHub Copilot 的 MCP 伺服器:

  1. F1。 在命令選項板中,搜尋並執行 MCP:新增伺服器

  2. 選擇 HTTP (Server-Sent Events) 作為傳輸類型。

  3. 輸入您在上一個步驟中複製的 MCP 端點的 URL。

  4. 使用產生的 伺服器 ID 並選取 工作區 ,將 MCP 伺服器連線儲存至您的工作區設定。

  5. 開啟命令選項板並執行 MCP:列出伺服器, 並確認您新增的伺服器已列出並正在執行。

  6. 在 Copilot 聊天中,選取 代理程式 模式並執行此提示:

    Say Hello
    

    當系統提示您執行工具時,請選取 [在此工作區中允許] ,這樣您就不必繼續授與權限。 提示會執行並傳回 Hello World 回應,並將函數執行資訊寫入記錄。

  7. 現在,在其中一個專案檔案中選取一些程式碼,然後執行下列提示:

    Save this snippet as snippet1
    

    Copilot 會儲存程式碼片段,並回應您的要求,並提供有關如何使用該工具擷取程式碼片段 getSnippets 的資訊。 同樣地,您可以在記錄中檢閱函式執行,並確認 saveSnippets 函式已執行。

  8. 在 Copilot 聊天中,執行此提示:

    Retrieve snippet1 and apply to NewFile
    

    Copilot 會擷取程式碼片段,將其新增至名為 NewFile的檔案,並執行它認為需要讓程式碼片段在您的專案中運作的其他任何動作。 Function 日誌顯示已呼叫getSnippets端點。

  9. 完成測試時,請按 Ctrl+C 以停止函式主機。

檢閱程式碼 (選用)

您可以檢閱定義 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 伺服器 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 伺服器 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 伺服器 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 伺服器 GitHub 存放庫中檢視完整的專案範本。

在本機驗證 MCP 伺服器工具之後,您可以將專案發佈至 Azure。

部署至 Azure

此專案已設定為使用 azd up 命令,將此專案部署至 Azure 之彈性使用量方案中的新函數應用程式。 此專案包含一組 Bicep 檔案,讓 azd 用來建立符合最佳做法之彈性使用量方案的安全部署。

  1. 在 Visual Studio Code 中,按 F1 以開啟命令選擇區。 搜尋並執行命令 Azure Developer CLI (azd): Package, Provison and Deploy (up)。 然後,使用您的 Azure 帳戶登入。

  2. 如果您尚未登入,請使用您的 Azure 帳戶進行驗證。

  3. 出現提示時,請提供這些必要的部署參數:

    參數 Description
    Azure 訂用帳戶 建立您資源所在位置的訂用帳戶。
    Azure 位置 要在其中建立包含新 Azure 資源之資源群組所在的 Azure 區域。 只會顯示目前支援彈性使用量方案的區域。

    命令成功完成之後,您會看到所建立資源的連結。

連接到您的遠端 MCP 伺服器

您的 MCP 伺服器現在正在 Azure 中執行。 當您存取這些工具時,您需要在請求中包含系統金鑰。 此金鑰為存取遠端 MCP 伺服器的用戶端提供一定程度的存取控制。 取得此金鑰之後,您可以將 GitHub Copilot 連線到遠端伺服器。

  1. 執行此腳本,該腳本會使用 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"
    
  2. 在 Visual Studio Code 中,按 F1 開啟命令面板,搜尋並執行命令 MCP: Open Workspace Folder MCP Configuraton,以開啟 mcp.json 組態檔。

  3. 在組態中 mcp.json ,尋找您先前新增的具名 MCP 伺服器,將 url 值變更為遠端 MCP 伺服器 URL,然後新增包含 headers.x-functions-key 複製的 MCP 伺服器存取金鑰的元素,如以下範例所示:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. 在開啟的視窗中選取伺服器名稱上方的 [mcp.json 按鈕,以重新啟動遠端 MCP 伺服器,這次使用您已部署的應用程式。

確認您的部署

您現在可以讓 GitHub Copilot 使用遠端 MCP 工具,就像在本機一樣,但現在程式碼可以在 Azure 中安全地執行。 重播您之前使用的相同命令,以確保一切正常運作。

清理資源

當您完成 MCP 伺服器和相關資源的使用時,請使用此命令從 Azure 刪除函式應用程式及其相關資源,以避免產生進一步的成本:

azd down --no-prompt

備註

--no-prompt 選項會 azd 指示刪除您的資源群組,而不需要您確認。 此命令不會影響您的本機程式碼專案。

後續步驟