Snabbstart: Värdservrar som skapats med MCP SDK:er på Azure Functions

I den här snabbstarten får du lära dig att vara värd för mcp-servrar (Azure Functions Model Context Protocol) som du skapar med hjälp av officiella MCP-SDK:er. Med planen Flexförbrukning kan du dra nytta av Azure Functions serverlösa skalning, betalningsmodell för användning och inbyggda säkerhetsfunktioner. Det är perfekt för MCP-servrar som använder streamable-http-transporten.

Den här artikeln använder ett MCP-exempelserverprojekt som skapats med hjälp av officiella MCP-SDK:er.

Tips/Råd

Functions tillhandahåller också ett MCP-tillägg som gör att du kan skapa MCP-servrar med hjälp av Azure Functions-programmeringsmodellen. Mer information finns i Snabbstart: Skapa en anpassad MCP-fjärrserver med Azure Functions.

Eftersom den nya servern körs i en Flex Consumption-plan, som följer en faktureringsmodell för betala för vad du använder , medför slutförandet av den här snabbstarten en liten kostnad på några cent eller mindre i ditt Azure-konto.

Viktigt!

Även om värdtjänst med MCP-servrar och Anpassade Hanterare stöds för alla språk, finns det i snabbstartsscenariot för närvarande bara exempel för C#, Python och TypeScript. Slutför den här snabbstarten genom att välja ett av de språk som stöds överst i artikeln.

Förutsättningar

Anmärkning

Det här exemplet kräver att du har behörighet att skapa en Microsoft Entra-app i den Azure-prenumeration som du använder.

Kom igång med ett exempelprojekt

Det enklaste sättet att komma igång är att klona ett MCP-serverexempelprojekt som skapats med officiella MCP-SDK:er:

  1. Öppna en mapp eller arbetsyta i Visual Studio Code där du vill skapa projektet.
  1. I terminalen kör du det här kommandot för att initiera .NET-exemplet:

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

    Det här kommandot hämtar projektfilerna från malllagringsplatsen och initierar projektet i den aktuella mappen. Flaggan -e anger ett namn för den aktuella miljön. I azdbehåller miljön en unik distributionskontext för din app och du kan definiera mer än en. Den används också i namnen på de resurser som du skapar i Azure.

  1. I terminalen kör du det här kommandot för att initiera TypeScript-exemplet:

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

    Det här kommandot hämtar projektfilerna från malllagringsplatsen och initierar projektet i den aktuella mappen. Flaggan -e anger ett namn för den aktuella miljön. I azdbehåller miljön en unik distributionskontext för din app och du kan definiera mer än en. Den används också i namnen på de resurser som du skapar i Azure.

  1. I terminalen kör du det här kommandot för att initiera Python-exemplet:

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

    Det här kommandot hämtar projektfilerna från malllagringsplatsen och initierar projektet i den aktuella mappen. Flaggan -e anger ett namn för den aktuella miljön. I azdbehåller miljön en unik distributionskontext för din app och du kan definiera mer än en. Den används också i namnen på de resurser som du skapar i Azure.

Kodprojektmallen är avsedd för en MCP-server med verktyg som har åtkomst till offentliga väder-API:er.

Kör MCP-servern lokalt

Visual Studio Code integreras med Azure Functions Core Tools så att du kan köra det här projektet på din lokala utvecklingsdator.

  1. Öppna terminalen i redigeraren (Ctrl+Shift+` )
  1. I rotkatalogen kör du func start för att starta servern. Terminalpanelen visar utdata från Core Tools.
  1. I rotkatalogen kör du npm install för att installera beroenden och kör npm run buildsedan .
  2. Starta servern genom att köra func start.
  1. I rotkatalogen kör du uv run func start för att skapa en virtuell miljö, installera beroenden och starta servern.

Testa servern med hjälp av GitHub Copilot

Följ dessa steg för att verifiera servern med hjälp av GitHub Copilot i Visual Studio Code:

  1. Öppna filen mcp.json i katalogen .vscode.

  2. Starta servern genom att välja knappen Start ovanför konfigurationen local-mcp-server .

  3. I fönstret Copilot Chat kontrollerar du att agentmodellen är vald, väljer ikonen Konfigurera verktyg och kontrollerar att den MCP Server:local-mcp-server är aktiverad i chatten.

  4. Kör den här uppmaningen i chatten:

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

    Copilot bör ringa ett av väderverktygen för att besvara den här frågan. När du uppmanas att köra verktyget väljer du Tillåt på den här arbetsytan så att du inte behöver fortsätta att regrantera den här behörigheten.

När du har verifierat verktygsfunktionen lokalt kan du stoppa servern och distribuera projektkoden till Azure.

Distribuera till Azure

Det här projektet är konfigurerat för att använda azd up kommandot för att distribuera projektet till en ny funktionsapp i en Flex Consumption-plan i Azure. Projektet innehåller en uppsättning Bicep-filer som azd använder för att skapa en säker distribution som följer metodtipsen.

  1. Logga in på Azure:

    azd login
    
  2. Konfigurera Visual Studio Code som ett förauktoriserat klientprogram:

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

    Ett förauktoriserat program kan autentisera till och komma åt MCP-servern utan att kräva fler medgivandemeddelanden.

  3. I Visual Studio Code trycker du på F1 för att öppna kommandopaletten. Sök efter och kör kommandot Azure Developer CLI (azd): Package, Provision and Deploy (up). Logga sedan in med ditt Azure-konto.

  4. Ange följande nödvändiga distributionsparametrar när du uppmanas att göra det:

    Parameter Description
    Azure-prenumeration Prenumeration där dina resurser skapas.
    Azure-lokalisering Azure-region där du kan skapa resursgruppen som innehåller de nya Azure-resurserna. Endast regioner som för närvarande stöder Flex Consumption-planen visas.

    När kommandot har slutförts visas länkar till de resurser som du skapade och slutpunkten för din distribuerade MCP-server. Anteckna funktionsappens namn, som du behöver för nästa avsnitt.

    Tips/Råd

    Om ett fel uppstår när kommandot körs azd up kör du kommandot igen. Du kan köra azd up flera gånger eftersom den hoppar över att skapa resurser som redan finns. Du kan också anropa azd up igen när du distribuerar uppdateringar till din tjänst.

Ansluta till den fjärranslutna MCP-servern

McP-servern körs nu i Azure. Om du vill ansluta GitHub Copilot till fjärrservern konfigurerar du det i inställningarna för arbetsytan.

  1. mcp.json I filen växlar du till fjärrservern genom att välja Stoppa för konfigurationen local-mcp-server och Starta i konfigurationenremote-mcp-server.

  2. När du uppmanas att ange funktionsappens domän anger du namnet på din funktionsapp som du antecknade i föregående avsnitt. När du uppmanas att autentisera till Microsoft väljer du Tillåt och väljer sedan ditt Azure-konto.

  3. Verifiera fjärrservern genom att ställa en fråga som:

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

    Copilot anropar ett av väderverktygen för att besvara frågan.

Tips/Råd

Du kan se utdata från en server genom att välja Mer...>Visa utdata. Utdata ger användbar information om möjliga anslutningsfel. Du kan också välja kugghjulsikonen för att ändra loggnivåerna till Spårningar för att få mer information om interaktionerna mellan klienten (Visual Studio Code) och servern.

Granska koden (valfritt)

Du kan granska koden som definierar MCP-servern:

MCP-serverkoden definieras i projektroten. Servern använder den officiella C#MCP SDK:t för att definiera dessa väderrelaterade verktyg:

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

Du kan visa den fullständiga projektmallen i Azure Functions .NET MCP SDK som är värd för GitHub-lagringsplatsen.

MCP-serverkoden definieras i server.py filen. Servern använder den officiella Python MCP SDK för att definiera väderrelaterade verktyg. Det här är definitionen av get_forecast verktyget:

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)

Du kan visa den fullständiga projektmallen i GitHub-lagringsplatsen för Azure Functions Python MCP SDK.

MCP-serverkoden definieras i src mappen . Servern använder den officiella Node.js MCP SDK för att definiera väderrelaterade verktyg. Det här är definitionen av get-forecast verktyget:

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

Du kan visa den fullständiga projektmallen i Azure Functions TypeScript MCP SDK som är värd för GitHub-lagringsplatsen.

Rensa resurser

När du är klar med mcp-servern och relaterade resurser använder du det här kommandot för att ta bort funktionsappen och dess relaterade resurser från Azure för att undvika ytterligare kostnader:

azd down