共用方式為


Azure Functions 的 MCP 工具觸發程式

使用 MCP 工具觸發程式在 模型內容通訊協定 (MCP) 伺服器中定義工具端點。 客戶端語言模型和代理可以使用工具來執行特定任務,例如儲存或存取程式碼片段。

如需安裝和組態詳細數據的詳細資訊,請參閱概

範例

備註

針對 C#,Azure Functions MCP 擴充功能僅支持 隔離的背景工作模型

此程式代碼會建立端點,以公開名為 SaveSnippet 的工具,以嘗試將具名代碼段保存到 Blob 記憶體。

private const string BlobPath = "snippets/{mcptoolargs.snippetname}.json";

[Function(nameof(SaveSnippet))]
[BlobOutput(BlobPath)]
public string SaveSnippet(
    [McpToolTrigger("save_snippet", "Saves a code snippet into your snippet collection.")]
        ToolInvocationContext context,
    [McpToolProperty("snippetname", "The name of the snippet.", isRequired: true)]
        string name,
    [McpToolProperty("snippet", "The code snippet.", isRequired: true)]
        string snippet
)
{
    return snippet;
}

此程式代碼會建立端點,以公開名為 GetSnippet 的工具,以嘗試依名稱從 Blob 記憶體擷取代碼段。

private const string BlobPath = "snippets/{mcptoolargs.snippetname}.json";

[Function(nameof(GetSnippet))]
public object GetSnippet(
    [McpToolTrigger("get_snippets", "Gets code snippets from your snippet collection.")]
        ToolInvocationContext context,
    [BlobInput(BlobPath)] string snippetContent
)
{
    return snippetContent;
}

函數 GetSnippet 的工具屬性在 中配置 Program.cs

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder
    .ConfigureMcpTool("get_snippets")
    .WithProperty("snippetname", "string", "The name of the snippet.", required: true);

builder.Build().Run();

小提示

上面的示例使用了文字字符串,例如“get_snippets”工具 Program.cs 的名稱和函數。 請考慮改用共用常數字串,讓專案中的內容保持同步。

如需完整的程式代碼範例,請參閱 SnippetTool.cs

此程式代碼會建立端點,以公開名為 SaveSnippets 的工具,以嘗試將具名代碼段保存到 Blob 記憶體。

@FunctionName("SaveSnippets")
@StorageAccount("AzureWebJobsStorage")
public String saveSnippet(
        @McpToolTrigger(
                name = "saveSnippets",
                description = "Saves a text snippet to your snippets collection."
        )
        String mcpToolInvocationContext,
        @McpToolProperty(
                name = "snippetName",
                propertyType = "string",
                description = "The name of the snippet.",
                required = true
        )
        String snippetName,
        @McpToolProperty(
                name = "snippet",
                propertyType = "string",
                description = "The content of the snippet.",
                required = true
        )
        String snippet,
        @BlobOutput(name = "outputBlob", path = "snippets/{mcptoolargs.snippetName}.json")
        OutputBinding<String> outputBlob,
        final ExecutionContext context
) {
    // Log the entire incoming JSON for debugging
    context.getLogger().info(mcpToolInvocationContext);

    // Log the snippet name and content
    context.getLogger().info("Saving snippet with name: " + snippetName);
    context.getLogger().info("Snippet content:\n" + snippet);

    // Write the snippet content to the output blob
    outputBlob.setValue(snippet);

    return "Successfully saved snippet '" + snippetName + "' with " + snippet.length() + " characters.";
}

此程式代碼會建立端點,以公開名為 GetSnippets 的工具,以嘗試依名稱從 Blob 記憶體擷取代碼段。

@FunctionName("GetSnippets")
@StorageAccount("AzureWebJobsStorage")
public String getSnippet(
        @McpToolTrigger(
                name = "getSnippets",
                description = "Gets a text snippet from your snippets collection."
        )
        String mcpToolInvocationContext,
        @McpToolProperty(
                name = "snippetName",
                propertyType = "string",
                description = "The name of the snippet.",
                required = true
        )
        String snippetName,
        @BlobInput(name = "inputBlob", path = "snippets/{mcptoolargs.snippetName}.json")
        String inputBlob,
        final ExecutionContext context
) {
    // Log the entire incoming JSON for debugging
    context.getLogger().info(mcpToolInvocationContext);

    // Log the snippet name and the fetched snippet content from the blob
    context.getLogger().info("Retrieving snippet with name: " + snippetName);
    context.getLogger().info("Snippet content:");
    context.getLogger().info(inputBlob);

    // Return the snippet content or a not found message
    if (inputBlob != null && !inputBlob.trim().isEmpty()) {
        return inputBlob;
    } else {
        return "Snippet '" + snippetName + "' not found.";
    }
}

如需完整的程式代碼範例,請參閱 Snippets.java

目前無法使用 JavaScript 的範例程式代碼。 如需使用 Node.js的一般指引,請參閱 TypeScript 範例。

此程式代碼會建立端點,以公開名為 savesnippet 的工具,以嘗試將具名代碼段保存到 Blob 記憶體。

import { app, InvocationContext, input, output, arg } from "@azure/functions";

app.mcpTool("saveSnippet", {
  toolName: SAVE_SNIPPET_TOOL_NAME,
  description: SAVE_SNIPPET_TOOL_DESCRIPTION,
  toolProperties: {
    [SNIPPET_NAME_PROPERTY_NAME]: arg.string().describe(SNIPPET_NAME_PROPERTY_DESCRIPTION),
    [SNIPPET_PROPERTY_NAME]: arg.string().describe(SNIPPET_PROPERTY_DESCRIPTION)
  },
  extraOutputs: [blobOutputBinding],
  handler: saveSnippet,
});

這段程式碼會 savesnippet 處理觸發器:

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;
}

此程式代碼會建立端點,以公開名為 getsnippet 的工具,以嘗試依名稱從 Blob 記憶體擷取代碼段。

import { app, InvocationContext, input, output, arg } from "@azure/functions";

app.mcpTool("getSnippet", {
  toolName: GET_SNIPPET_TOOL_NAME,
  description: GET_SNIPPET_TOOL_DESCRIPTION,
  toolProperties: {
    [SNIPPET_NAME_PROPERTY_NAME]: arg.string().describe(SNIPPET_NAME_PROPERTY_DESCRIPTION)
  },
  extraInputs: [blobInputBinding],
  handler: getSnippet,
});

這段程式碼會 getsnippet 處理觸發器:

export async function getSnippet(
  _toolArguments: unknown,
  context: InvocationContext
): Promise<string> {
  console.info("Getting snippet");

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

  console.info(`Snippet name: ${snippetName}`);

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

  // Get the content from blob binding - properly retrieving from extraInputs
  const snippetContent = context.extraInputs.get(blobInputBinding);

  if (!snippetContent) {
    return `Snippet '${snippetName}' not found`;
  }

  console.info(`Retrieved snippet: ${snippetName}`);
  return snippetContent as string;
}

如需完整的程式代碼範例,請參閱 snippetsMcpTool.ts

此程式代碼會 mcp_tool_trigger 使用裝飾專案來建立端點,以公開名為 save_snippet 的工具,以嘗試將具名代碼段保存到 Blob 記憶體。

@app.mcp_tool_trigger(
    arg_name="context",
    tool_name="save_snippet",
    description="Save a snippet with a name.",
    tool_properties=tool_properties_save_snippets_json,
)
@app.blob_output(arg_name="file", 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"

此程式代碼會 mcp_tool_trigger 使用裝飾專案來建立端點,以公開名為 get_snippet 的工具,以嘗試依名稱從 Blob 記憶體擷取代碼段。

@app.mcp_tool_trigger(
    arg_name="context",
    tool_name="get_snippet",
    description="Retrieve a snippet by name.",
    tool_properties=tool_properties_get_snippets_json,
)
@app.blob_input(arg_name="file", connection="AzureWebJobsStorage", path=_BLOB_PATH)
def get_snippet(file: func.InputStream, context) -> str:
    """
    Retrieves a snippet by name from Azure Blob Storage.

    Args:
        file (func.InputStream): The input binding to read the snippet from Azure Blob Storage.
        context: The trigger context containing the input arguments.

    Returns:
        str: The content of the snippet or an error message.
    """
    snippet_content = file.read().decode("utf-8")
    logging.info(f"Retrieved snippet: {snippet_content}")
    return snippet_content

如需完整的程式碼範例,請參閱 function_app.py

這很重要

MCP 延伸模組目前不支援PowerShell應用程式。

屬性

C# 連結庫會使用 McpToolTriggerAttribute 來定義函式觸發程式。

屬性的建構函式會採用下列參數:

參數 說明
ToolName (必要) MCP 觸發程式端點所公開之工具的名稱。
說明 (選擇性) 用戶端工具端點的易記描述。

請參閱 使用方式 ,瞭解如何將端點的屬性定義為輸入參數。

附註

@McpToolTrigger 注會建立函式,以公開遠端 MCP 伺服器中的工具端點。

註解支援下列組態選項:

參數 說明
name (必要) MCP 觸發程式端點所公開之工具的名稱。
描述 (選擇性) 用戶端工具端點的易記描述。

@McpToolProperty註解會定義工具的個別內容。 函數中的每個屬性參數都應該使用此註釋進行註釋。

@McpToolProperty註解支援下列組態選項:

參數 說明
name (必要) 公開給用戶端之工具屬性的名稱。
屬性類型 (必要) 工具性質的類型。 有效類型為: stringnumberintegerbooleanobject
描述 (選擇性) 工具屬性用途的描述。
必填 (選擇性) 如果設定為 true,則需要工具屬性作為工具呼叫的引數。 預設為 false

裝飾

僅適用於 Python v2 程式設計模型。

mcp_tool_trigger裝飾器需要 1.24.0 版或更高版本的azure-functions套件。 支援 mcp_tool_trigger下列 MCP 觸發程式屬性:

房產 說明
arg_name 函式程式代碼中用來存取執行內容的變數名稱(通常 context為 )。
tool_name (必要)函式端點所公開的 MCP 伺服器工具名稱。
描述 函式端點所公開的MCP伺服器工具描述。
tool_properties 一或多個屬性物件的 JSON 字串表示法,這些物件會將工具的屬性公開給用戶端。

設定

觸發程式支援這些系結選項,這些選項定義於您的程式代碼中:

選項 說明
類型 必須設定為 mcpToolTrigger。 僅搭配泛型定義使用。
toolName (必要)函式端點所公開的 MCP 伺服器工具名稱。
描述 函式端點所公開的MCP伺服器工具描述。
toolProperties 對象的陣列,這個陣列 toolProperty 會將工具的屬性公開給用戶端。
extraOutputs 定義時,將函式輸出傳送至另一個系結。
處理程式 包含實際函式程式碼的方法。

如需完整範例,請參閱範例一節。

用法

MCP 工具觸發程式可以繫結至下列類型:

類型 說明
工具調用內容 代表工具呼叫的物件,包括工具名稱和呼叫的引數。
JSON 可序列化型別 函式會嘗試將工具引數還原序列化為純舊的 CLR 物件 (POCO) 類型。 此類型也用於 定義工具性質

繫結至 JSON 可序列化類型時,您也可以選擇性地包含 ToolInvocationContext 類型的參數,以存取工具呼叫資訊。

工具屬性

MCP 用戶端會使用引數呼叫工具,以提供工具作業的資料和內容。 用戶端知道如何根據工具公告為通訊協定一部分的屬性來收集和傳遞這些引數。 因此,您需要在函數程式碼中定義工具的屬性。

當您定義工具屬性時,預設為選擇性屬性,而且用戶端可以在叫用工具時省略它。 如果工具沒有屬性就無法運作,您必須明確地將屬性標示為必要。

備註

舊版的 MCP 延伸模組預覽預設需要所有工具屬性。 此行為從版本 1.0.0-preview.7開始變更,現在您必須明確地將屬性標示為必要。

在 C# 中,您可以透過數種方式定義工具的屬性。 您使用哪種方法取決於程式碼樣式偏好。 選項包括:

  • 您的函數使用屬性取得 McpToolProperty 輸入參數。
  • 您可以使用屬性定義自訂類型,而函式會繫結至該類型。
  • 您可以使用 來 FunctionsApplicationBuilder 定義檔案中的 Program.cs 內容。

您可以將 屬性套用 McpToolProperty 至函式中的輸入系結樣式參數,以定義一或多個工具屬性。

McpToolPropertyAttribute 類型支援下列屬性:

房產 說明
屬性名稱 公開給用戶端的工具屬性名稱。
說明 工具屬性用途的描述。
是必要 (選用)如果設定為 true,則需要工具屬性作為工具呼叫的引數。 預設為 false

內容類型是從您套用屬性的參數類型推斷出來的。 例如[McpToolProperty("snippetname", "The name of the snippet.", true)] string name,在 MCP 訊息中定義名為 type 的snippetname必要工具內容string

您可以在SaveSnippet中查看工具中使用的這些屬性。

在 Java 中,您可以使用個別函數參數上的註釋來 @McpToolProperty 定義工具內容。 代表工具屬性的每個參數都應該使用此註釋進行註釋,指定屬性名稱、類型、描述以及是否必要。

您可以在 範例中看到這些註釋。

您可以在觸發器定義的 toolProperties 欄位中設定工具屬性,這是物件陣 ToolProperty 列的字串表示法。

ToolProperty物件具有下列結構:

{
    "propertyName": "Name of the property",
    "propertyType": "Type of the property",
    "description": "Optional property description",
    "isRequired": true|false,
    "isArray": true|false
}

物件的 ToolProperty 欄位包括:

房產 說明
屬性名稱 公開給用戶端的工具屬性名稱。
屬性類型 工具屬性的類型。 有效類型為: stringnumberintegerbooleanobject。 請參閱 isArray 陣列類型。
描述 工具屬性用途的描述。
是必填 (選用)如果設定為 true,則需要工具屬性作為工具呼叫的引數。 預設為 false
是陣列 (選用)如果設定為 true,工具屬性是指定屬性類型的陣列。 預設為 false

你可以將欄位提供 toolProperties 為物件陣列 ToolProperty ,或使用 arg 輔助 @azure/functions 工具以更安全型別的方式定義屬性:

  toolProperties: {
    [SNIPPET_NAME_PROPERTY_NAME]: arg.string().describe(SNIPPET_NAME_PROPERTY_DESCRIPTION)
  }

如需詳細資訊,請參閱 範例

host.json 設定

host.json 檔案包含控制MCP觸發行為的設定。 如需可用設定的詳細資訊,請參閱host.json設定一節。

適用於 Azure Functions 的 Azure OpenAI 延伸模組