Compartir a través de


Desencadenador de herramientas MCP para Azure Functions

Use el desencadenador de la herramienta MCP para definir puntos de conexión de herramientas en un servidor de Protocolo de contenido de modelos (MCP). Los agentes y modelos de lenguaje de cliente pueden usar herramientas para realizar tareas específicas, como almacenar o acceder a fragmentos de código.

Para obtener información sobre los detalles de instalación y configuración, vea la información general.

Ejemplo

Nota:

En C#, la extensión MCP de Azure Functions solo admite el modelo de trabajo aislado.

Este código crea un punto de conexión para exponer una herramienta denominada SaveSnippet que intenta conservar un fragmento de código con nombre en Blob Storage.

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

Este código crea un punto de conexión para exponer una herramienta denominada GetSnippet que intenta recuperar un fragmento de código por nombre de Blob Storage.

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

Las propiedades de la herramienta para la GetSnippet función se configuran en 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();

Sugerencia

En el ejemplo anterior se usaron cadenas literales para cosas como el nombre de la herramienta "get_snippets" en y Program.cs la función . Considere la posibilidad de usar cadenas constantes compartidas para mantener las cosas sincronizadas en el proyecto.

Para obtener el ejemplo de código completo, consulte SnippetTool.cs.

Este código crea un punto de conexión para exponer una herramienta denominada SaveSnippets que intenta conservar un fragmento de código con nombre en Blob Storage.

@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.";
}

Este código crea un punto de conexión para exponer una herramienta denominada GetSnippets que intenta recuperar un fragmento de código por nombre de Blob Storage.

@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.";
    }
}

Para obtener el ejemplo de código completo, consulte Snippets.java.

El código de ejemplo para JavaScript no está disponible actualmente. Consulte los ejemplos de TypeScript para obtener instrucciones generales mediante Node.js.

Este código crea un punto de conexión para exponer una herramienta denominada savesnippet que intenta conservar un fragmento de código con nombre en Blob Storage.

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

Este código controla el savesnippet desencadenador:

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

Este código crea un punto de conexión para exponer una herramienta denominada getsnippet que intenta recuperar un fragmento de código por nombre de Blob Storage.

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

Este código controla el getsnippet desencadenador:

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

Para obtener el ejemplo de código completo, consulte snippetsMcpTool.ts.

Este código usa el mcp_tool_trigger decorador para crear un punto de conexión para exponer una herramienta denominada save_snippet que intenta conservar un fragmento de código con nombre en Blob Storage.

@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"

Este código usa el mcp_tool_trigger decorador para crear un punto de conexión para exponer una herramienta denominada get_snippet que intenta recuperar un fragmento de código por nombre de Blob Storage.

@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

Para obtener el ejemplo de código completo, consulte function_app.py.

Importante

La extensión MCP no admite actualmente aplicaciones de PowerShell.

Atributos

Las bibliotecas de C# usan McpToolTriggerAttribute para definir el desencadenador de función.

El constructor del atributo toma los parámetros siguientes:

Parámetro Descripción
ToolName (Obligatorio) nombre de la herramienta que expone el punto de conexión del desencadenador de MCP.
Descripción (Opcional) descripción sencilla del punto de conexión de la herramienta para los clientes.

Consulte Uso para obtener información sobre cómo definir las propiedades del punto de conexión como parámetros de entrada.

anotaciones

La @McpToolTrigger anotación crea una función que expone un punto de conexión de herramienta en el servidor MCP remoto.

La anotación admite las siguientes opciones de configuración:

Parámetro Descripción
name (Obligatorio) nombre de la herramienta que expone el punto de conexión del desencadenador de MCP.
descripción (Opcional) descripción sencilla del punto de conexión de la herramienta para los clientes.

La @McpToolProperty anotación define propiedades individuales para las herramientas. Cada parámetro de propiedad de la función debe anotarse con esta anotación.

La @McpToolProperty anotación admite las siguientes opciones de configuración:

Parámetro Descripción
name (Obligatorio) nombre de la propiedad de herramienta que se expone a los clientes.
propertyType (Obligatorio) tipo de la propiedad de herramienta. Los tipos válidos son: string, number, integer, boolean, . object
descripción (Opcional) descripción de lo que hace la propiedad de herramienta.
requerido (Opcional) si se establece en true, la propiedad de la herramienta es necesaria como argumento para las llamadas a herramientas. Tiene como valor predeterminado false.

Decoradores

Solo se aplica al modelo de programación de Python v2.

El mcp_tool_trigger decorador requiere la versión 1.24.0 o posterior del azure-functions paquete. Las siguientes propiedades del desencadenador MCP se admiten en mcp_tool_trigger:

Propiedad Descripción
arg_name Nombre de variable (normalmente context) usado en el código de función para acceder al contexto de ejecución.
tool_name (Obligatorio) Nombre de la herramienta de servidor MCP expuesta por el punto de conexión de la función.
descripción Descripción de la herramienta de servidor MCP expuesta por el punto de conexión de la función.
tool_properties Representación de cadena JSON de uno o varios objetos de propiedad que exponen las propiedades de la herramienta a los clientes.

Configuración

El desencadenador admite estas opciones de enlace, que se definen en el código:

Opciones Descripción
tipo Debe establecerse en mcpToolTrigger. Solo se usa con definiciones genéricas.
toolName (Obligatorio) Nombre de la herramienta de servidor MCP expuesta por el punto de conexión de la función.
descripción Descripción de la herramienta de servidor MCP expuesta por el punto de conexión de la función.
toolProperties Matriz de toolProperty objetos que exponen las propiedades de la herramienta a los clientes.
extraOutputs Cuando se define, envía la salida de función a otro enlace.
manejador de Método que contiene el código de función real.

Consulte la sección de ejemplos para ver ejemplos completos.

Uso

El desencadenador de la herramienta MCP puede enlazarse a los siguientes tipos:

Tipo Descripción
ToolInvocationContext Objeto que representa la llamada a la herramienta, incluido el nombre de la herramienta y los argumentos de la llamada.
Tipos serializables con JSON Functions intenta deserializar los argumentos de la herramienta en un tipo clR (POCO) antiguo sin formato. Este tipo también se usa para definir las propiedades de la herramienta.

Al enlazar a un tipo serializable JSON, también puede incluir un parámetro de tipo ToolInvocationContext para acceder a la información de llamada de la herramienta.

Propiedades de la herramienta

Los clientes de MCP invocan herramientas con argumentos para proporcionar datos y contexto para la operación de la herramienta. Los clientes saben cómo recopilar y pasar estos argumentos en función de las propiedades que la herramienta anuncia como parte del protocolo. Por lo tanto, debe definir las propiedades de la herramienta en el código de función.

Al definir una propiedad de herramienta, es opcional de forma predeterminada y el cliente puede omitirla al invocar la herramienta. Debe marcar explícitamente las propiedades según sea necesario si la herramienta no puede funcionar sin ellas.

Nota:

Las versiones anteriores de la versión preliminar de la extensión MCP hicieron que todas las propiedades de la herramienta sean necesarias de forma predeterminada. Este comportamiento cambió a partir de la versión 1.0.0-preview.7y ahora debe marcar explícitamente las propiedades según sea necesario.

En C#, puede definir propiedades para las herramientas de varias maneras. Qué enfoque se usa es una cuestión de preferencia de estilo de código. Las opciones son:

  • La función toma parámetros de entrada mediante el McpToolProperty atributo .
  • Defina un tipo personalizado con las propiedades y la función se enlaza a ese tipo.
  • FunctionsApplicationBuilder Use para definir propiedades en el Program.cs archivo.

Puede definir una o varias propiedades de herramienta aplicando el McpToolProperty atributo a parámetros de estilo de enlace de entrada en la función.

El McpToolPropertyAttribute tipo admite estas propiedades:

Propiedad Descripción
PropertyName (Nombre de la propiedad) Nombre de la propiedad de herramienta que se expone a los clientes.
Descripción Descripción de lo que hace la propiedad de la herramienta.
EsRequerido (Opcional) Si se establece en true, la propiedad de la herramienta es necesaria como argumento para las llamadas a herramientas. Tiene como valor predeterminado false.

El tipo de propiedad se deduce del tipo del parámetro al que se aplica el atributo . Por ejemplo [McpToolProperty("snippetname", "The name of the snippet.", true)] string name , define una propiedad de herramienta necesaria denominada snippetname de tipo string en mensajes MCP.

Puede ver estos atributos usados en la SaveSnippet herramienta en los ejemplos.

En Java, se definen las propiedades de la herramienta mediante la @McpToolProperty anotación en parámetros de función individuales. Cada parámetro que representa una propiedad de herramienta debe anotarse con esta anotación, especificando el nombre de propiedad, el tipo, la descripción y si es necesario.

Puede ver estas anotaciones usadas en los ejemplos.

Puede configurar las propiedades de la herramienta en el campo de la definición del toolProperties desencadenador, que es una representación de cadena de una matriz de ToolProperty objetos.

Un ToolProperty objeto tiene esta estructura:

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

Los campos de un ToolProperty objeto son:

Propiedad Descripción
propertyName Nombre de la propiedad de herramienta que se expone a los clientes.
propertyType Tipo de la propiedad de herramienta. Los tipos válidos son: string, number, integer, boolean, . object Consulte isArray para ver los tipos de matriz.
descripción Descripción de lo que hace la propiedad de la herramienta.
isRequired (Opcional) Si se establece en true, la propiedad de la herramienta es necesaria como argumento para las llamadas a herramientas. Tiene como valor predeterminado false.
isArray (Opcional) Si se establece en true, la propiedad de herramienta es una matriz del tipo de propiedad especificado. Tiene como valor predeterminado false.

Puedes proporcionar el toolProperties campo como un array de ToolProperty objetos, o puedes usar los arg helpers de @azure/functions para definir propiedades de una forma más segura para tipos:

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

Para más información, consulte Ejemplos.

configuración de host.json

El archivo host.json contiene la configuración que controla los comportamientos del desencadenador MCP. Consulte la sección de configuración de host.json para más información sobre las opciones de configuración disponibles.

Extensión de Azure OpenAI para Azure Functions