Udostępnij przez


Szybki start: serwery hostowane utworzone za pomocą pakietów SDK MCP na platformie Azure Functions

Szybki start: w tym przewodniku dowiesz się, jak hostować usługi Azure Functions na serwerach Model Context Protocol (MCP), które tworzysz za pomocą oficjalnych zestawów SDK MCP. "Plan hostingowy Flex Consumption umożliwia korzystanie z bezserwerowego skalowania usługi Azure Functions, modelu rozliczeń z płatnością zgodnie z rzeczywistym użyciem oraz wbudowanych funkcji zabezpieczeń." Doskonale nadaje się do serwerów MCP korzystających z transportu streamable-http.

W tym artykule użyto przykładowego projektu serwera MCP utworzonego przy użyciu oficjalnych zestawów SDK MCP.

Wskazówka

Usługa Functions udostępnia również rozszerzenie MCP, które umożliwia tworzenie serwerów MCP przy użyciu modelu programowania usługi Azure Functions. Aby uzyskać więcej informacji, zobacz Szybki start: tworzenie niestandardowego zdalnego serwera MCP przy użyciu usługi Azure Functions.

Ponieważ nowy serwer działa w ramach planu Flex Consumption, który jest zgodny z modelem rozliczeń „płać za to, co zużywasz”, ukończenie tego przewodnika 'Quickstart' wiąże się z nieznacznymi kosztami na koncie Azure, rzędu kilku centów lub nawet mniej.

Ważne

Hostowanie serwerów MCP przy użyciu niestandardowych procedur obsługi jest obsługiwane we wszystkich językach, jednak ten scenariusz szybkiego startu zawiera obecnie tylko przykłady języków C#, Python i TypeScript. Aby ukończyć ten szybki start, wybierz jeden z obsługiwanych języków na górze artykułu.

Wymagania wstępne

  • Python 3.11 lub nowszy
  • uv do zarządzania pakietami w języku Python

Uwaga / Notatka

Ten przykład wymaga uprawnień do tworzenia aplikacji Microsoft Entra w używanej subskrypcji platformy Azure.

Wprowadzenie do przykładowego projektu

Najprostszym sposobem rozpoczęcia pracy jest sklonowanie przykładowego projektu serwera MCP utworzonego przy użyciu oficjalnych zestawów SDK MCP:

  1. W programie Visual Studio Code otwórz folder lub obszar roboczy, w którym chcesz utworzyć projekt.
  1. W Terminalu uruchom to polecenie, aby zainicjować przykład .NET:

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

    To polecenie ściąga pliki projektu z repozytorium szablonów i inicjuje projekt w bieżącym folderze. Flaga -e ustawia nazwę bieżącego środowiska. W azd środowisko systemowe zapewnia unikatowy kontekst wdrażania dla twojej aplikacji i można zdefiniować więcej niż jeden z nich. Jest ona również używana w nazwach zasobów tworzonych na platformie Azure.

  1. W terminalu uruchom to polecenie, aby zainicjować przykład języka TypeScript:

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

    To polecenie ściąga pliki projektu z repozytorium szablonów i inicjuje projekt w bieżącym folderze. Flaga -e ustawia nazwę bieżącego środowiska. W azd środowisko systemowe zapewnia unikatowy kontekst wdrażania dla twojej aplikacji i można zdefiniować więcej niż jeden z nich. Jest ona również używana w nazwach zasobów tworzonych na platformie Azure.

  1. W terminalu uruchom następujące polecenie, aby zainicjować przykład języka Python:

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

    To polecenie ściąga pliki projektu z repozytorium szablonów i inicjuje projekt w bieżącym folderze. Flaga -e ustawia nazwę bieżącego środowiska. W azd środowisko systemowe zapewnia unikatowy kontekst wdrażania dla twojej aplikacji i można zdefiniować więcej niż jeden z nich. Jest ona również używana w nazwach zasobów tworzonych na platformie Azure.

Szablon projektu kodu jest przeznaczony dla serwera MCP z narzędziami, które uzyskują dostęp do publicznych interfejsów API pogody.

Uruchamianie serwera MCP lokalnie

Program Visual Studio Code integruje się z narzędziami Azure Functions Core Tools , aby umożliwić uruchamianie tego projektu na lokalnym komputerze programistycznym.

  1. Otwórz terminal w edytorze (Ctrl+Shift+` )
  1. W katalogu głównym uruchom polecenie func start , aby uruchomić serwer. Na panelu Terminal są wyświetlane dane wyjściowe z narzędzi Core Tools.
  1. W katalogu głównym uruchom polecenie npm install , aby zainstalować zależności, a następnie uruchom polecenie npm run build.
  2. Aby uruchomić serwer, uruchom polecenie func start.
  1. W katalogu głównym uruchom polecenie uv run func start , aby utworzyć środowisko wirtualne, zainstalować zależności i uruchomić serwer.

Serwer testowy przy użyciu narzędzia GitHub Copilot

Aby zweryfikować serwer przy użyciu narzędzia GitHub Copilot w programie Visual Studio Code, wykonaj następujące kroki:

  1. Otwórz plik mcp.json w katalogu .vscode.

  2. Uruchom serwer, wybierając przycisk Uruchom powyżej local-mcp-server konfiguracji.

  3. W oknie Czat Copilot upewnij się, że wybrano model Agenta, wybierz ikonę Konfiguruj narzędzia i sprawdź, czy MCP Server:local-mcp-server są włączone w czacie.

  4. Uruchom ten monit na czacie:

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

    Copilot powinien zadzwonić do jednego z narzędzi pogodowych, aby pomóc odpowiedzieć na to pytanie. Po wyświetleniu monitu o uruchomienie narzędzia wybierz pozycję Zezwalaj w tym obszarze roboczym , aby nie trzeba było ponownie udzielać tego uprawnienia.

Po zweryfikowaniu funkcji narzędzia lokalnie możesz zatrzymać serwer i wdrożyć kod projektu na platformie Azure.

Wdrażanie na platformie Azure

Ten projekt jest skonfigurowany do użycia azd up polecenia w celu wdrożenia tego projektu w nowej aplikacji funkcji w planie Flex Consumption na platformie Azure. Projekt zawiera zestaw plików Bicep używanych azd do tworzenia bezpiecznego wdrożenia, które jest zgodne z najlepszymi praktykami.

  1. Zaloguj się do platformy Azure:

    azd login
    
  2. Skonfiguruj program Visual Studio Code jako wstępnie uwierzytelnioną aplikację kliencką:

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

    Wstępnie uwierzytelniona aplikacja może uwierzytelniać się i uzyskiwać dostęp do serwera MCP bez konieczności monitowania o większą zgodę.

  3. W programie Visual Studio Code naciśnij F1 , aby otworzyć paletę poleceń. Wyszukaj i uruchom polecenie Azure Developer CLI (azd): Package, Provision and Deploy (up). Następnie zaloguj się przy użyciu konta platformy Azure.

  4. Po wyświetleniu monitu podaj następujące wymagane parametry wdrożenia:

    Parameter Description
    Subskrypcja platformy Azure Subskrypcja, w której są tworzone zasoby.
    Lokalizacja platformy Azure Region platformy Azure, w którym ma zostać utworzona grupa zasobów zawierająca nowe zasoby platformy Azure. Wyświetlane są tylko regiony, które obecnie obsługują plan Flex Consumption.

    Po pomyślnym zakończeniu działania polecenia zostaną wyświetlone linki do utworzonych zasobów i punktu końcowego wdrożonego serwera MCP. Zanotuj nazwę funkcji aplikacji, której potrzebujesz w następnej sekcji.

    Wskazówka

    Jeśli podczas uruchamiania azd up polecenia wystąpi błąd, uruchom ponownie polecenie. Można uruchomić azd up wielokrotnie, ponieważ pomija tworzenie już istniejących zasobów. Możesz również ponownie wywołać azd up podczas wdrażania aktualizacji dla usługi.

Nawiązywanie połączenia z zdalnym serwerem MCP

Serwer MCP działa teraz na platformie Azure. Aby połączyć narzędzie GitHub Copilot z serwerem zdalnym, skonfiguruj go w ustawieniach obszaru roboczego.

  1. W pliku mcp.json, przejdź na serwer zdalny, wybierając Zatrzymaj dla local-mcp-server konfiguracji i Uruchom w remote-mcp-server konfiguracji.

  2. Po wyświetleniu monitu o domenę aplikacji funkcji wprowadź nazwę swojej aplikacji funkcji, którą zanotowałeś w poprzedniej sekcji. Po wyświetleniu monitu o uwierzytelnienie w firmie Microsoft wybierz pozycję Zezwalaj , a następnie wybierz konto platformy Azure.

  3. Zweryfikuj serwer zdalny, zadając pytanie, takie jak:

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

    Copilot wywołuje jedno z narzędzi pogodowych, aby odpowiedzieć na zapytanie.

Wskazówka

Dane wyjściowe serwera można wyświetlić, wybierając pozycję Więcej...>Pokaż dane wyjściowe. Dane wyjściowe zawierają przydatne informacje o możliwych błędach połączenia. Możesz także wybrać ikonę ustawień, aby zmienić poziom dziennika na Traces, co pozwoli uzyskać więcej informacji o interakcjach między klientem (Visual Studio Code) a serwerem.

Przejrzyj kod (opcjonalnie)

Możesz przejrzeć kod definiujący serwer MCP:

Kod serwera MCP jest zdefiniowany w katalogu głównym projektu. Serwer używa oficjalnego zestawu SDK MCP w języku C#, aby zdefiniować te narzędzia związane z pogodą:

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()}
                """));
    }
}

Pełny szablon projektu można wyświetlić w repozytorium GitHub przeznaczonym dla usługi hostowania Azure Functions .NET MCP SDK.

Kod serwera MCP jest zdefiniowany w server.py pliku. Serwer używa oficjalnego zestawu SDK MCP języka Python do definiowania narzędzi związanych z pogodą. Jest to definicja get_forecast narzędzia:

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)

Kompletny szablon projektu można wyświetlić w repozytorium GitHub Azure Functions Python MCP SDK Hosting.

Kod serwera MCP jest zdefiniowany w folderze src . Serwer używa oficjalnego zestawu SDK Node.js MCP do definiowania narzędzi związanych z pogodą. Jest to definicja get-forecast narzędzia:

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

Kompletny szablon projektu można znaleźć w repozytorium GitHub Azure Functions TypeScript MCP SDK hosting.

Uprzątnij zasoby

Po zakończeniu pracy z serwerem MCP i powiązanymi zasobami użyj tego polecenia, aby usunąć aplikację funkcji i powiązane z nią zasoby z platformy Azure, aby uniknąć ponoszenia dodatkowych kosztów:

azd down