Compartir por


Inicio rápido: Hospedaje de servidores creados con SDK de MCP en Azure Functions

En esta guía rápida, aprendes cómo hospedar servidores de Azure Functions en el Protocolo de Contexto de Modelo (MCP) que creas utilizando los SDK oficiales de MCP. El hospedaje en el plan Flex Consumption le permite aprovechar la escala sin servidor de Azure Functions, el modelo de facturación de pago por uso y las características de seguridad integradas. Es perfecto para los servidores MCP que usan el transporte streamable-http.

En este artículo se usa un proyecto de servidor MCP de ejemplo creado mediante SDK de MCP oficiales.

Sugerencia

Functions también proporciona una extensión MCP que permite crear servidores MCP mediante el modelo de programación de Azure Functions. Para más información, consulte Inicio rápido: Compilación de un servidor MCP remoto personalizado mediante Azure Functions.

Dado que el nuevo servidor se ejecuta en un plan de consumo flexible, que sigue un modelo de facturación de pago por uso , completar este inicio rápido conlleva un pequeño costo de unos pocos centavos o menos en su cuenta de Azure.

Importante

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

Prerrequisitos

  • Python 3.11 o superior
  • uv para la administración de paquetes de Python

Nota:

Este ejemplo requiere que tenga permiso para crear una aplicación de Microsoft Entra en la suscripción de Azure que use.

Comienza con un proyecto de ejemplo

La manera más fácil de empezar es clonar un proyecto de ejemplo de servidor MCP creado con SDK de MCP oficiales:

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

    azd init --template mcp-sdk-functions-hosting-dotnet -e mcpsdkserver-dotnet
    

    Este comando extrae los archivos del proyecto del repositorio de plantillas 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 se usa en los nombres de los recursos que crea en Azure.

  1. En el terminal, ejecute este comando para inicializar el ejemplo de TypeScript:

    azd init --template mcp-sdk-functions-hosting-node  -e mcpsdkserver-node
    

    Este comando extrae los archivos del proyecto del repositorio de plantillas 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 se usa en los nombres de los recursos que crea en Azure.

  1. En el terminal, ejecute este comando para inicializar el ejemplo de Python:

    azd init --template mcp-sdk-functions-hosting-python -e mcpsdkserver-python
    

    Este comando extrae los archivos del proyecto del repositorio de plantillas 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 se usa en los nombres de los recursos que crea en Azure.

La plantilla de proyecto de código es para un servidor MCP con herramientas que acceden a las API meteorológicas públicas.

Ejecución local del servidor MCP

Visual Studio Code se integra con Azure Functions Core Tools para permitirle ejecutar este proyecto en el equipo de desarrollo local.

  1. Abra Terminal en el editor (Ctrl+Shift+` )
  1. En el directorio raíz, ejecute func start para iniciar el servidor. El panel Terminal muestra la salida de Core Tools.
  1. En el directorio raíz, ejecute npm install para instalar dependencias y, a continuación, ejecute npm run build.
  2. Para iniciar el servidor, ejecute func start.
  1. En el directorio raíz, ejecute uv run func start para crear un entorno virtual, instalar dependencias e iniciar el servidor.

Servidor de prueba mediante GitHub Copilot

Para comprobar el servidor mediante GitHub Copilot en Visual Studio Code, siga estos pasos:

  1. Abra el archivo mcp.json en el directorio .vscode.

  2. Inicie el servidor seleccionando el botón Iniciar situado encima de la local-mcp-server configuración.

  3. En la ventana Chat de Copilot, asegúrese de que el modelo del agente está seleccionado, seleccione el icono Configurar herramientas y compruebe que MCP Server:local-mcp-server está habilitado en el chat.

  4. Ejecute este comando en el chat:

    Return the weather forecast for New York City using #local-mcp-server
    

    Copilot debe llamar a una de las herramientas meteorológicas para ayudar a responder a esta pregunta. Cuando se le pida que ejecute la herramienta, seleccione Permitir en este área de trabajo para que no tenga que seguir con la reasignación de este permiso.

Después de comprobar la funcionalidad de la herramienta localmente, puede detener el servidor e implementar el código del proyecto en Azure.

Implementación en Azure

Este proyecto está configurado para usar el comando azd up 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 de Bicep que azd usa para crear una implementación segura que siga los procedimientos recomendados.

  1. Inicie sesión en Azure:

    azd login
    
  2. Configure Visual Studio Code como una aplicación cliente autenticada previamente:

    azd env set PRE_AUTHORIZED_CLIENT_IDS aebc6443-996d-45c2-90f0-388ff96faa56
    

    Una aplicación autenticada previamente puede autenticarse y acceder al servidor MCP sin necesidad de más solicitudes de consentimiento.

  3. 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.

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

    Parámetro Description
    Suscripción a 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.

    Una vez que el comando se complete correctamente, verá vínculos a los recursos que creó y el punto de conexión del servidor MCP implementado. Anote el nombre de la aplicación de funciones, que necesita para la sección siguiente.

    Sugerencia

    Si se produce un error al ejecutar el azd up comando, vuelva a ejecutar el comando. Puede ejecutarse azd up repetidamente porque omite la creación de los recursos que ya existen. También puede llamar de nuevo a azd up al implementar actualizaciones en su servicio.

Conexión al servidor MCP remoto

El servidor MCP ahora se está ejecutando en Azure. Para conectar GitHub Copilot al servidor remoto, configúrelo en la configuración del área de trabajo.

  1. En el mcp.json archivo, cambie al servidor remoto seleccionando Detener para la local-mcp-server configuración e Iniciar en la remote-mcp-server configuración.

  2. Cuando se le solicite el dominio de la aplicación de funciones, escriba el nombre de la aplicación de funciones que anotó en la sección anterior. Cuando se le pida que se autentique en Microsoft, seleccione Permitir y elija su cuenta de Azure.

  3. Compruebe el servidor remoto haciendo una pregunta como:

    Return the weather forecast for Seattle using #remote-mcp-server.
    

    Copilot llama a una de las herramientas meteorológicas para responder a la consulta.

Sugerencia

Para ver la salida de un servidor, seleccione Más...>Mostrar salida. La salida proporciona información útil sobre posibles errores de conexión. También puede seleccionar el icono de ajustes para cambiar los niveles de log a Trazas para obtener más detalles sobre las interacciones entre el cliente (Visual Studio Code) y el servidor.

Revisión del código (opcional)

Puede revisar el código que define el servidor MCP:

El código del servidor MCP se define en la raíz del proyecto. El servidor usa el SDK oficial de MCP de C# para definir estas herramientas relacionadas con el tiempo:

using ModelContextProtocol;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Globalization;
using System.Text.Json;

namespace QuickstartWeatherServer.Tools;

[McpServerToolType]
public sealed class WeatherTools
{
    [McpServerTool, Description("Get weather alerts for a US state.")]
    public static async Task<string> GetAlerts(
        HttpClient client,
        [Description("The US state to get alerts for. Use the 2 letter abbreviation for the state (e.g. NY).")] string state)
    {
        using var jsonDocument = await client.ReadJsonDocumentAsync($"/alerts/active/area/{state}");
        var jsonElement = jsonDocument.RootElement;
        var alerts = jsonElement.GetProperty("features").EnumerateArray();

        if (!alerts.Any())
        {
            return "No active alerts for this state.";
        }

        return string.Join("\n--\n", alerts.Select(alert =>
        {
            JsonElement properties = alert.GetProperty("properties");
            return $"""
                    Event: {properties.GetProperty("event").GetString()}
                    Area: {properties.GetProperty("areaDesc").GetString()}
                    Severity: {properties.GetProperty("severity").GetString()}
                    Description: {properties.GetProperty("description").GetString()}
                    Instruction: {properties.GetProperty("instruction").GetString()}
                    """;
        }));
    }

    [McpServerTool, Description("Get weather forecast for a location.")]
    public static async Task<string> GetForecast(
        HttpClient client,
        [Description("Latitude of the location.")] double latitude,
        [Description("Longitude of the location.")] double longitude)
    {
        var pointUrl = string.Create(CultureInfo.InvariantCulture, $"/points/{latitude},{longitude}");
        using var jsonDocument = await client.ReadJsonDocumentAsync(pointUrl);
        var forecastUrl = jsonDocument.RootElement.GetProperty("properties").GetProperty("forecast").GetString()
            ?? throw new Exception($"No forecast URL provided by {client.BaseAddress}points/{latitude},{longitude}");

        using var forecastDocument = await client.ReadJsonDocumentAsync(forecastUrl);
        var periods = forecastDocument.RootElement.GetProperty("properties").GetProperty("periods").EnumerateArray();

        return string.Join("\n---\n", periods.Select(period => $"""
                {period.GetProperty("name").GetString()}
                Temperature: {period.GetProperty("temperature").GetInt32()}°F
                Wind: {period.GetProperty("windSpeed").GetString()} {period.GetProperty("windDirection").GetString()}
                Forecast: {period.GetProperty("detailedForecast").GetString()}
                """));
    }
}

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

El código del servidor MCP se define en el server.py archivo . El servidor usa el SDK oficial de MCP de Python para definir herramientas relacionadas con el tiempo. Esta es la definición de la get_forecast herramienta:

import os
import sys
import warnings
import logging
from typing import Any
from pathlib import Path

import httpx
from azure.identity import OnBehalfOfCredential, ManagedIdentityCredential
from mcp.server.fastmcp import FastMCP
from fastmcp.server.dependencies import get_http_request
from starlette.requests import Request
from starlette.responses import HTMLResponse

# Initialize FastMCP server
mcp = FastMCP("weather", stateless_http=True)

# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """Get weather forecast for a location.

    Args:
        latitude: Latitude of the location
        longitude: Longitude of the location
    """
    # First get the forecast grid endpoint
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)

    if not points_data:
        return "Unable to fetch forecast data for this location."

    # Get the forecast URL from the points response
    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)

    if not forecast_data:
        return "Unable to fetch detailed forecast."

    # Format the periods into a readable forecast
    periods = forecast_data["properties"]["periods"]
    forecasts = []
    for period in periods[:5]:  # Only show next 5 periods
        forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
        forecasts.append(forecast)

    return "\n---\n".join(forecasts)

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

El código del servidor MCP se define en la src carpeta . El servidor usa el SDK de MCP de Node.js oficial para definir herramientas relacionadas con el tiempo. Esta es la definición de la get-forecast herramienta:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { ManagedIdentityCredential, OnBehalfOfCredential } from '@azure/identity';

const NWS_API_BASE = "https://api.weather.gov";
const USER_AGENT = "weather-app/1.0";

// Function to create a new server instance for each request (stateless)
export const createServer = () => {
  const server = new McpServer({
    name: "weather",
    version: "1.0.0",
  });
  server.registerTool(
    "get-forecast",
    {
      title: "Get Weather Forecast",
      description: "Get weather forecast for a location",
      inputSchema: {
        latitude: z.number().min(-90).max(90).describe("Latitude of the location"),
        longitude: z
          .number()
          .min(-180)
          .max(180)
          .describe("Longitude of the location"),
      },
      outputSchema: z.object({
        forecast: z.string(),
      }),
    },
    async ({ latitude, longitude }) => {
      // Get grid point data
      const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`;
      const pointsData = await makeNWSRequest<PointsResponse>(pointsUrl);

      if (!pointsData) {
        const output = { forecast: `Failed to retrieve grid point data for coordinates: ${latitude}, ${longitude}. This location may not be supported by the NWS API (only US locations are supported).` };
        return {
          content: [{ type: "text", text: JSON.stringify(output) }],
          structuredContent: output,
        };
      }

      const forecastUrl = pointsData.properties?.forecast;
      if (!forecastUrl) {
        const output = { forecast: "Failed to get forecast URL from grid point data" };
        return {
          content: [{ type: "text", text: JSON.stringify(output) }],
          structuredContent: output,
        };
      }

      // Get forecast data
      const forecastData = await makeNWSRequest<ForecastResponse>(forecastUrl);
      if (!forecastData) {
        const output = { forecast: "Failed to retrieve forecast data" };
        return {
          content: [{ type: "text", text: JSON.stringify(output) }],
          structuredContent: output,
        };
      }

      const periods = forecastData.properties?.periods || [];
      if (periods.length === 0) {
        const output = { forecast: "No forecast periods available" };
        return {
          content: [{ type: "text", text: JSON.stringify(output) }],
          structuredContent: output,
        };
      }

      // Format forecast periods
      const formattedForecast = periods.map((period: ForecastPeriod) =>
        [
          `${period.name || "Unknown"}:`,
          `Temperature: ${period.temperature || "Unknown"}°${period.temperatureUnit || "F"}`,
          `Wind: ${period.windSpeed || "Unknown"} ${period.windDirection || ""}`,
          `${period.shortForecast || "No forecast available"}`,
          "---",
        ].join("\n"),
      );

      const forecastText = `Forecast for ${latitude}, ${longitude}:\n\n${formattedForecast.join("\n")}`;
      const output = { forecast: forecastText };

      return {
        content: [{ type: "text", text: forecastText }],
        structuredContent: output,
      };
    },
  );
  return server;
}

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

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