Inicio rápido: Creación de un servidor MCP remoto personalizado mediante Azure Functions

En esta guía de inicio rápido, creará un servidor personalizado del Model Context Protocol (MCP) a partir de un proyecto de plantilla mediante Azure Developer CLI (azd). Este servidor MCP usa la extensión de servidor MCP de Azure Functions para proporcionar herramientas para modelos, agentes y asistentes de IA. También puede usar la extensión de servidor MCP para crear aplicaciones de MCP interactivas.

Después de ejecutar el proyecto localmente y comprobar el código mediante GitHub Copilot, se implementa en una nueva aplicación de funciones sin servidor en Azure Functions que sigue los procedimientos recomendados actuales para implementaciones seguras y escalables.

Dado que la nueva aplicación se ejecuta en el plan de consumo flexible, que sigue un pay-for-what-use modelo de facturación, completar este inicio rápido conlleva un pequeño costo de unos pocos centavos de USD o menos en su cuenta de Azure.

Importante

Aunque crear servidores MCP personalizados es compatible con todos los lenguajes de Functions, este escenario de inicio rápido actualmente solo tiene ejemplos para C#, Java, JavaScript, Python y TypeScript. Para completar este inicio rápido, seleccione uno de estos idiomas admitidos en la parte superior del artículo.

En este artículo se admite la versión 4 del modelo de programación de Node.js para Azure Functions.

En este artículo se admite la versión 2 del modelo de programación de Python para Azure Functions.

Prerrequisitos

  • kit para desarrolladores de Java 17
    • Si usa otra versión compatible de Java, actualice el archivo del pom.xml proyecto.
    • Establezca la variable de entorno JAVA_HOME en la ubicación de instalación de la versión correcta del kit de desarrollo de Java (JDK).
  • Apache Maven 3.8.x

Inicialización del proyecto

Use el comando azd init para crear un proyecto de código de Azure Functions local a partir de una plantilla.

  1. En Visual Studio Code, abra una carpeta o un área de trabajo donde quiera crear el proyecto.
  1. En el terminal, ejecute este azd init comando:

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

    Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. También forma parte del nombre del grupo de recursos que crea en Azure.

  1. En el terminal local o el símbolo del sistema, ejecute este comando azd init:

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

    Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. También forma parte de los nombres de los recursos que crea en Azure.

  1. En el terminal local o el símbolo del sistema, ejecute este comando azd init:

    azd init --template remote-mcp-functions-javascript -e mcpserver-js
    

    Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. También forma parte de los nombres de los recursos que crea en Azure.

  1. En el terminal local o el símbolo del sistema, ejecute este comando azd init:

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

    Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. También forma parte de los nombres de los recursos que crea en Azure.

  1. En el terminal local o el símbolo del sistema, ejecute este comando azd init:

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

    Este comando extrae los archivos del proyecto del repositorio template e inicializa el proyecto en la carpeta actual. La marca -e establece un nombre para el entorno actual. En azd, el entorno mantiene un contexto de implementación único para la aplicación y puede definir más de uno. También forma parte de los nombres de los recursos que crea en Azure.

Inicio del emulador de almacenamiento

Use el emulador de Azurite para simular una conexión de cuenta de Azure Storage al ejecutar el proyecto de código localmente.

  1. Si aún no lo ha hecho, instale Azurite.

  2. Presione F1. En la paleta de comandos, busque y ejecute el comando Azurite: Start para iniciar el emulador de almacenamiento local.

Ejecución local del servidor MCP

En una ventana de terminal, vaya a la carpeta del FunctionsMcpTool proyecto:

cd src/FunctionsMcpTool

En una ventana de terminal, vaya a la carpeta del FunctionsMcpTool proyecto:

cd samples/FunctionsMcpTool

Visual Studio Code se integra con Azure Functions Core tools para permitirle ejecutar este proyecto en el equipo de desarrollo local. Para iniciar la aplicación de Functions localmente, presione F5 o seleccione el icono Ejecutar y depurar en la barra de actividad del lado izquierdo.

El panel Terminal muestra la salida de Core Tools. La aplicación se inicia en el panel Terminal y puede ver los nombres de las funciones que se ejecutan localmente.

Comprobación mediante GitHub Copilot

La plantilla de proyecto incluye un archivo .vscode/mcp.json que ya define un servidor local-mcp-function que apunta al punto de conexión de MCP local. Use esta configuración para comprobar el código mediante GitHub Copilot en Visual Studio Code:

  1. Abra el .vscode/mcp.json archivo y seleccione el botón Iniciar situado encima de la local-mcp-function configuración.

  2. En la ventana Copilot Chat, asegúrese de que está seleccionado el Agent, seleccione el Configurar herramientas y compruebe que MCP Server:local-mcp-function está habilitado en el chat.

  3. Ejecute este comando:

    Say Hello
    

    Cuando se le pida que ejecute la herramienta, seleccione Permitir en este área de trabajo para que no tenga que seguir concediéndole permiso. La solicitud se ejecuta y devuelve una respuesta Hola mundo, y la información de ejecución de funciones se escribe en los logs.

  4. Ahora, seleccione código en uno de los archivos de su proyecto y ejecute este comando:

    Save this snippet as snippet1
    

    Copilot almacena el fragmento de código y responde a la solicitud con información sobre cómo recuperar el fragmento de código mediante la herramienta getSnippets. De nuevo, puede revisar la ejecución de la función en los registros y comprobar que se ejecutó la saveSnippets función.

  5. En Copilot chat, ejecute esta indicación:

    Retrieve snippet1 and apply to NewFile
    

    Copilot recupera los fragmentos de código, los agrega a un archivo denominado NewFile y hace lo que considere necesario para que el fragmento de código funcione en el proyecto. Los registros de funciones muestran que se llamó al getSnippets endpoint.

  6. Cuando haya terminado de probar, presione Ctrl+C para detener el host de Functions.

Revisión del código (opcional)

Puede revisar el código que define las herramientas del servidor MCP:

El código de función de las herramientas de servidor MCP se define en la src/functions carpeta . El registro de funciones de MCP expone estas funciones como herramientas del servidor MCP:

const PROPERTY_TYPE = "string";

// Hello function - responds with hello message
async function mcpToolHello(_toolArguments, context) {
    console.log(_toolArguments);
    // Get name from the tool arguments
    const mcptoolargs = context.triggerMetadata.mcptoolargs;
    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.',
  const mcptoolargs = context.triggerMetadata.mcptoolargs;

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

// Register the GetSnippet tool
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,
});

Puede ver la plantilla de proyecto completa en el repositorio Azure Functions servidor MCP de JavaScript GitHub.

El código de función de las herramientas de servidor MCP se define en la src carpeta . El McpToolTrigger atributo expone las funciones como herramientas del servidor 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!";
}

public class SnippetsTool(ILogger<SnippetsTool> logger)
{
    private const string BlobPath = "snippets/{mcptoolargs.Name}.json";

    private static BlobServiceClient GetBlobServiceClient() =>
        new(Environment.GetEnvironmentVariable("AzureWebJobsStorage"));

    [Function(nameof(GetSnippet))]
    public Snippet? GetSnippet(
        [McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)]
            ToolInvocationContext context,
        [McpToolProperty(SnippetNamePropertyName, SnippetNamePropertyDescription, true)]
            string name,
        [BlobInput(BlobPath)] string? snippetContent
    )
    {
        if (snippetContent is null)
        {
            return null;
        }

        return new Snippet { Name = name, Content = snippetContent };
    }

Puede ver la plantilla de proyecto completa en el repositorio Azure Functions .NET MCP Server GitHub.

El código de función de las herramientas de servidor MCP se define en la samples/FunctionsMcpTool/src/main/java/com/function/ carpeta . La @McpToolTrigger anotación expone las funciones como herramientas de servidor MCP:

@FunctionName("HelloWorld")
public String logCustomTriggerInput(
        @McpToolTrigger(
                name = "helloWorld",
                description = "Says hello and logs the messages that are provided.")
        McpToolInvocationContext mcpToolInvocationContext,
        @McpToolProperty(
            name = "messages",
            propertyType = "string",
            description = "The messages to be logged.",
            isRequired = true,
            isArray = true)
        String messages,
        final ExecutionContext functionExecutionContext
) {
@FunctionName("SaveSnippets")
@StorageAccount("AzureWebJobsStorage")
public String saveSnippet(
        @McpToolTrigger(
                name = "saveSnippets",
                description = "Saves a text snippet to your snippets collection.")
        String mcpToolInvocationContext,
        @McpToolProperty(
            name = SNIPPET_NAME_PROPERTY_NAME,
            propertyType = "string",
            description = "The name of the snippet.",
            isRequired = true)
        String snippetName,
        @McpToolProperty(
            name = SNIPPET_PROPERTY_NAME,
            propertyType = "string",
            description = "The content of the snippet.",
            isRequired = true)
        String snippet,
        @BlobOutput(name = "outputBlob", path = BLOB_PATH)
        OutputBinding<String> outputBlob,
        final ExecutionContext functionExecutionContext
) {
    // Log the entire incoming JSON for debugging
    functionExecutionContext.getLogger().info(mcpToolInvocationContext);

    // Log the snippet name and content
    functionExecutionContext.getLogger().info("Saving snippet with name: " + snippetName);
    functionExecutionContext.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.";

Puede ver la plantilla de proyecto completa en el repositorio Azure Functions Java MCP Server GitHub.

El código de función para las herramientas de servidor MCP se define en el src/function_app.py archivo . Las anotaciones de la función MCP exponen estas funciones como herramientas del servidor MCP:

from hello_tool_with_auth import bp as auth_bp
app.register_blueprint(auth_bp)

# Constants for the Azure Blob Storage container, file, and blob path
_SNIPPET_NAME_PROPERTY_NAME = "snippetname"
_BLOB_PATH = "snippets/{mcptoolargs." + _SNIPPET_NAME_PROPERTY_NAME + "}.json"
    """Hello world."""
    return "Hello I am MCPTool!"


@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()

Puede ver la plantilla de proyecto completa en el repositorio Azure Functions Python MCP Server GitHub.

El código de función de las herramientas de servidor MCP se define en la mcp-tools/src carpeta . El registro de funciones de MCP expone estas funciones como herramientas del servidor MCP:

// Hello function - responds with hello message
export async function mcpToolHello(_toolArguments: unknown, context: InvocationContext): Promise<string> {
    const mcptoolargs = context.triggerMetadata.mcptoolargs as {
        name?: string;
    };
    const name = mcptoolargs?.name;

    context.log(`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 responds with a hello message.',
    toolProperties: {
        name: arg.string().describe('Required property to identify the caller.').optional()
    },
    handler: mcpToolHello
});
// Register the GetSnippet tool
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,
});

// Register the SaveSnippet tool
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,
});

Puede ver la plantilla de proyecto completa en el repositorio Azure Functions TypeScript MCP Server GitHub.

Después de comprobar las herramientas del servidor MCP localmente, puede publicar el proyecto en Azure.

Implementación en Azure

Este proyecto está configurado para usar azd para implementar este proyecto en una nueva aplicación de funciones en un plan de consumo flexible en Azure. El proyecto incluye un conjunto de archivos Bicep que azd usa para crear una implementación segura en un plan Consumo flexible que sigue los procedimientos recomendados.

  1. En Visual Studio Code, presione F1 para abrir la paleta de comandos. Busque y ejecute el comando Azure Developer CLI (azd): Package, Provision and Deploy (up). A continuación, inicie sesión con su cuenta de Azure.

  2. Cuando se le solicite, seleccione estos parámetros de implementación necesarios:

    Parámetro Description
    Suscripción de Azure Suscripción en la que se crean los recursos.
    Ubicación de Azure Región de Azure en la que se va a crear el grupo de recursos que contiene los nuevos recursos de Azure. Solo se muestran las regiones que admiten actualmente el Plan de consumo flexible.
    vnetEnabled False para omitir la creación de recursos de red virtual, lo que simplifica la implementación.

    Una vez que el comando se complete correctamente, verá vínculos a los recursos que creó.

Conexión al servidor MCP remoto

El servidor MCP ahora se está ejecutando en Azure. La plantilla de proyecto incluye una remote-mcp-function entrada en .vscode/mcp.json que ya está configurada para conectarse al servidor remoto. Dado que la autorización MCP integrada está habilitada de forma predeterminada, Visual Studio Code controla el flujo de inicio de sesión de OAuth automáticamente al conectarse.

  1. Obtén el nombre de la aplicación de funciones de tu implementación ejecutando este comando en el terminal:

    azd env get-value AZURE_FUNCTION_NAME
    
  2. En .vscode/mcp.json, seleccione Iniciar encima de la remote-mcp-function configuración.

  3. Cuando se le solicite, escriba el nombre de la aplicación de funciones del paso anterior.

  4. Visual Studio Code le pide que inicie sesión con Microsoft Entra. Siga las indicaciones de autenticación para autorizar el acceso al servidor MCP remoto.

Comprobación de la implementación

Ahora puede hacer que GitHub Copilot use sus herramientas de MCP remotas tal como lo hacía localmente, pero el código se ejecuta de forma segura en Azure. Reproduzca los mismos comandos que usó anteriormente para asegurarse de que todo funciona correctamente.

Limpieza de recursos

Cuando haya terminado de trabajar con el servidor MCP y los recursos relacionados, use este comando para eliminar la aplicación de funciones y sus recursos relacionados de Azure para evitar incurrir en costos adicionales:

azd down 

Pasos siguientes