Udostępnij za pomocą


Szybki start: tworzenie niestandardowego zdalnego serwera MCP przy użyciu usługi Azure Functions

W tym szybkim przewodniku startowym utworzysz niestandardowy zdalny serwer protokołu kontekstu modelu (MCP) z projektu szablonu przy użyciu interfejsu wiersza polecenia dla deweloperów platformy Azure (azd). Serwer MCP używa rozszerzenia serwera MCP usługi Azure Functions do udostępniania narzędzi dla modeli sztucznej inteligencji, agentów i asystentów. Po uruchomieniu projektu lokalnie i zweryfikowaniu kodu przy użyciu narzędzia GitHub Copilot wdrożysz go w nowej aplikacji funkcji bezserwerowej w usłudze Azure Functions, która jest zgodna z bieżącymi najlepszymi rozwiązaniami dotyczącymi bezpiecznych i skalowalnych wdrożeń.

Wskazówka

Funkcje umożliwiają również wdrożenie istniejącego projektu kodu serwera MCP w aplikacji planu Flex Consumption bez konieczności wprowadzania zmian w projekcie kodu. Aby uzyskać więcej informacji, zobacz Szybki start: hostowanie istniejących serwerów MCP w usłudze Azure Functions.

Ponieważ nowa aplikacja jest uruchamiana w ramach planu Flex Consumption, który korzysta z modelu rozliczeń pay-as-you-go, ukończenie tego przewodnika szybkiego startu wiąże się z niewielkimi kosztami, liczonymi w kilku centach USD lub mniej na Twoim koncie Azure.

Ważne

Chociaż tworzenie niestandardowych serwerów MCP jest obsługiwane we wszystkich językach obsługiwanych przez Functions, ten scenariusz szybkiego startu zawiera obecnie tylko przykłady dla języków C#, Python i TypeScript. ** Aby ukończyć ten szybki start, wybierz jeden z tych obsługiwanych języków na górze artykułu.

Ten artykuł obsługuje wersję 4 modelu programowania Node.js dla usługi Azure Functions.

Ten artykuł obsługuje wersję 2 modelu programowania w języku Python dla usługi Azure Functions.

Wymagania wstępne

Inicjowanie projektu

Użyj polecenia , azd init aby utworzyć lokalny projekt kodu usługi Azure Functions na podstawie szablonu.

  1. W programie Visual Studio Code otwórz folder lub obszar roboczy, w którym chcesz utworzyć projekt.
  1. W terminalu uruchom następujące azd init polecenie:

    azd init --template remote-mcp-functions-dotnet -e mcpserver-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 nazwie grupy zasobów utworzonej na platformie Azure.

  1. W lokalnym terminalu lub wierszu polecenia uruchom następujące azd init polecenie:

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

    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 lokalnym terminalu lub wierszu polecenia uruchom następujące azd init polecenie:

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

    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 lokalnym terminalu lub wierszu polecenia uruchom następujące azd init polecenie:

    azd init --template remote-mcp-functions-python -e mcpserver-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.

Uruchamianie emulatora magazynu

Użyj emulatora usługi Azurite, aby symulować połączenie konta usługi Azure Storage podczas lokalnego uruchamiania projektu kodu.

  1. Jeśli jeszcze tego nie zrobiono, zainstaluj aplikację Azurite.

  2. Naciśnij F1. W palecie komend wyszukaj i uruchom polecenie Azurite: Start, aby uruchomić emulator magazynu lokalnego.

Uruchamianie serwera MCP lokalnie

Program Visual Studio Code integruje się z narzędziami Azure Functions Core , aby umożliwić uruchamianie tego projektu na lokalnym komputerze deweloperów przy użyciu emulatora Azurite.

  1. Aby uruchomić funkcję lokalnie, naciśnij F5 lub ikonę Uruchom i debuguj na pasku działań po lewej stronie. Na panelu Terminal są wyświetlane dane wyjściowe z narzędzi Core Tools. Aplikacja zostanie uruchomiona na panelu Terminal i będzie widoczna nazwa funkcji uruchomionych lokalnie.

  2. Zanotuj lokalny punkt końcowy serwera MCP (na przykład http://localhost:7071/runtime/webhooks/mcp), który służy do konfigurowania narzędzia GitHub Copilot w programie Visual Studio Code.

Weryfikowanie przy użyciu narzędzia GitHub Copilot

Aby zweryfikować kod, dodaj uruchomiony projekt jako serwer MCP dla narzędzia GitHub Copilot w programie Visual Studio Code:

  1. Naciśnij F1. W palecie poleceń wyszukaj i uruchom narzędzie MCP: Dodaj serwer.

  2. Wybierz dla typu transportu pozycję HTTP (Server-Sent Events).

  3. Wprowadź adres URL punktu końcowego MCP skopiowanego w poprzednim kroku.

  4. Użyj wygenerowanego identyfikatora serwera i wybierz pozycję Obszar roboczy , aby zapisać połączenie serwera MCP z ustawieniami obszaru roboczego.

  5. Otwórz paletę poleceń i uruchom narzędzie MCP: Wyświetl listę serwerów i sprawdź, czy dodany serwer jest wymieniony i uruchomiony.

  6. Na czacie Copilot wybierz pozycję Tryb agenta i uruchom następujący monit:

    Say Hello
    

    Po wyświetleniu monitu o uruchomienie narzędzia wybierz pozycję Zezwalaj w tym obszarze roboczym , aby nie trzeba było udzielać uprawnień. Prompt jest uruchamiany, zwraca Hello World odpowiedź, a informacje o wykonaniu funkcji są zapisywane w dziennikach.

  7. Teraz wybierz kod w jednym z plików projektu i uruchom następujący monit:

    Save this snippet as snippet1
    

    Copilot przechowuje fragment kodu i odpowiada na żądanie, podając informacje o sposobie pobierania fragmentu getSnippets kodu za pomocą narzędzia. Ponownie możesz przejrzeć wykonywanie funkcji w dziennikach i sprawdzić, czy funkcja została uruchomiona saveSnippets .

  8. Na czacie Copilot uruchom następujący monit:

    Retrieve snippet1 and apply to NewFile
    

    Copilot pobiera fragmenty kodu, dodaje go do pliku o nazwie NewFilei wykonuje cokolwiek innego, co uważa, że jest potrzebne, aby fragment kodu działał w projekcie. Dzienniki usługi Functions pokazują, że punkt końcowy getSnippets został wywołany.

  9. Po zakończeniu testowania naciśnij Ctrl+C, aby zatrzymać hosta funkcji.

Przejrzyj kod (opcjonalnie)

Możesz przejrzeć kod definiujący narzędzia serwera MCP:

Kod funkcji dla narzędzi serwera MCP jest zdefiniowany w folderze src . Atrybut McpToolTrigger uwidacznia funkcje jako narzędzia serwera MCP:

[Function(nameof(SayHello))]
public string SayHello(
    [McpToolTrigger(HelloToolName, HelloToolDescription)] ToolInvocationContext context
)
{
    logger.LogInformation("Saying hello");
    return "Hello I am MCP Tool!";
}
    [Function(nameof(GetSnippet))]
    public object GetSnippet(
        [McpToolTrigger(GetSnippetToolName, GetSnippetToolDescription)]
            ToolInvocationContext context,
        [BlobInput(BlobPath)] string snippetContent
    )
    {
        return snippetContent;
    }

    [Function(nameof(SaveSnippet))]
    [BlobOutput(BlobPath)]
    public string SaveSnippet(
        [McpToolTrigger(SaveSnippetToolName, SaveSnippetToolDescription)]
            ToolInvocationContext context,
        [McpToolProperty(SnippetNamePropertyName, SnippetNamePropertyDescription, true)]
            string name,
        [McpToolProperty(SnippetPropertyName, SnippetPropertyDescription, true)]
            string snippet
    )
    {
        return snippet;
    }
}

Pełny szablon projektu można wyświetlić w repozytorium GitHub serwera MCP platformy .NET usługi Azure Functions .

Kod funkcji dla narzędzi serwera MCP jest zdefiniowany w folderze src/main/java/com/function/ . Adnotacja @McpToolTrigger uwidacznia funkcje jako narzędzia serwera MCP:

            description = "The messages to be logged.",
            isRequired = true,
            isArray = true)
        String messages,
        final ExecutionContext functionExecutionContext
) {
    functionExecutionContext.getLogger().info("Hello, World!");
    functionExecutionContext.getLogger().info("Tool Name: " + mcpToolInvocationContext.getName());
    functionExecutionContext.getLogger().info("Transport Type: " + mcpToolInvocationContext.getTransportType());
    
    // Handle different transport types
    if (mcpToolInvocationContext.isHttpStreamable()) {
        functionExecutionContext.getLogger().info("Session ID: " + mcpToolInvocationContext.getSessionid());
    } else if (mcpToolInvocationContext.isHttpSse()) {
        if (mcpToolInvocationContext.getClientinfo() != null) {
            functionExecutionContext.getLogger().info("Client: " + 
                mcpToolInvocationContext.getClientinfo().get("name").getAsString() + " v" +
    // Write the snippet content to the output blob
    outputBlob.setValue(snippet);
    
    return "Successfully saved snippet '" + snippetName + "' with " + snippet.length() + " characters.";
}

/**
 * Azure Function that handles retrieving a text snippet from Azure Blob Storage.
 * <p>
 * The function is triggered by an MCP Tool Trigger. The snippet name is provided
 * as an MCP tool property, and the snippet content is read from the blob at the 
 * path derived from the snippet name.
 *
 * @param mcpToolInvocationContext The JSON input from the MCP tool trigger.
 * @param snippetName   The name of the snippet to retrieve, provided as an MCP tool property.
 * @param inputBlob     The Azure Blob input binding that fetches the snippet content.
 * @param functionExecutionContext       The execution context for logging.
 */
@FunctionName("GetSnippets")
@StorageAccount("AzureWebJobsStorage")
public String getSnippet(
        @McpToolTrigger(
            name = "getSnippets",
            description = "Gets a text snippet from your snippets collection.")
        String mcpToolInvocationContext,
        @McpToolProperty(
            name = SNIPPET_NAME_PROPERTY_NAME,
            propertyType = "string",
            description = "The name of the snippet.",
            isRequired = true)
        String snippetName,
        @BlobInput(name = "inputBlob", path = BLOB_PATH)
        String inputBlob,
        final ExecutionContext functionExecutionContext
) {
    // Log the entire incoming JSON for debugging
    functionExecutionContext.getLogger().info(mcpToolInvocationContext);

    // Log the snippet name and the fetched snippet content from the blob

Pełny szablon projektu można wyświetlić w repozytorium GitHub serwera MCP w języku Java usługi Azure Functions .

Kod funkcji dla narzędzi serwera MCP jest zdefiniowany w src/function_app.py pliku . Adnotacje funkcji MCP uwidaczniają te funkcje jako narzędzia serwera MCP:

tool_properties_save_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_save_snippets_object])
tool_properties_get_snippets_json = json.dumps([prop.to_dict() for prop in tool_properties_get_snippets_object])


@app.generic_trigger(
    arg_name="context",
    type="mcpToolTrigger",
    toolName="hello_mcp",
    description="Hello world.",
    toolProperties="[]",
)
def hello_mcp(context) -> None:
    """

@app.generic_trigger(
    arg_name="context",
    type="mcpToolTrigger",
    toolName="save_snippet",
    description="Save a snippet with a name.",
    toolProperties=tool_properties_save_snippets_json,
)
@app.generic_output_binding(arg_name="file", type="blob", 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"

Pełny szablon projektu można wyświetlić w repozytorium GitHub serwera MCP w języku Python usługi Azure Functions .

Kod funkcji dla narzędzi serwera MCP jest zdefiniowany w folderze src . Rejestracja funkcji MCP uwidacznia te funkcje jako narzędzia serwera MCP:

export async function mcpToolHello(_toolArguments:unknown, context: InvocationContext): Promise<string> {
    console.log(_toolArguments);
    // Get name from the tool arguments
    const mcptoolargs = context.triggerMetadata.mcptoolargs as {
        name?: string;
    };
    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.',
    toolProperties:{
        name: arg.string().describe('Required property to identify the caller.').optional()
    },
    handler: mcpToolHello
});
// SaveSnippet function - saves a snippet with a name
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;
}

Można wyświetlić pełny szablon projektu w repozytorium GitHub Azure Functions TypeScript MCP Server.

Po zweryfikowaniu narzędzi serwera MCP lokalnie możesz opublikować projekt 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 utworzenia bezpiecznego wdrożenia w planie zużycia Flex, który jest zgodny z najlepszymi praktykami.

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

  2. Jeśli jeszcze się nie zalogowałeś, uwierzytelnij się przy użyciu konta platformy Azure.

  3. 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 zobaczysz linki do utworzonych zasobów.

Nawiązywanie połączenia z zdalnym serwerem MCP

Serwer MCP działa teraz na platformie Azure. Gdy uzyskujesz dostęp do narzędzi, musisz dołączyć klucz systemowy do żądania. Ten klucz zapewnia stopień kontroli dostępu dla klientów, którzy uzyskują dostęp do zdalnego serwera MCP. Po otrzymaniu tego klucza możesz połączyć narzędzie GitHub Copilot z serwerem zdalnym.

  1. Uruchom ten skrypt, który używa azd interfejsu wiersza polecenia platformy Azure, aby wyświetlić zarówno adres URL serwera MCP, jak i klucz systemowy (mcp_extension) wymagany do uzyskania dostępu do narzędzi:

    eval $(azd env get-values --output dotenv)
    MCP_EXTENSION_KEY=$(az functionapp keys list --resource-group $AZURE_RESOURCE_GROUP \
        --name $AZURE_FUNCTION_NAME --query "systemKeys.mcp_extension" -o tsv)
    printf "MCP Server URL: %s\n" "https://$SERVICE_API_NAME.azurewebsites.net/runtime/webhooks/mcp"
    printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY"
    
  2. W programie Visual Studio Code naciśnij F1 , aby otworzyć paletę poleceń, wyszukaj i uruchom polecenie MCP: Open Workspace Folder MCP Configuraton, które otwiera mcp.json plik konfiguracji.

  3. mcp.json W konfiguracji znajdź dodany wcześniej nazwany serwer MCP, zmień url wartość na zdalny adres URL serwera MCP i dodaj headers.x-functions-key element zawierający skopiowany klucz dostępu serwera MCP, jak w tym przykładzie:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Wybierz przycisk Start powyżej nazwy serwera w otwartym mcp.json , aby ponownie uruchomić zdalny serwer MCP, tym razem przy użyciu wdrożonej aplikacji.

Zweryfikuj wdrożenie

Teraz możesz używać zdalnych narzędzi MCP za pomocą GitHub Copilot tak samo jak lokalnie, ale kod działa teraz bezpiecznie w Azure. Powtórz te same polecenia, które były używane wcześniej, aby upewnić się, że wszystko działa poprawnie.

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 --no-prompt

Uwaga / Notatka

Opcja --no-prompt powoduje azd usunięcie grupy zasobów bez potwierdzenia. To polecenie nie ma wpływu na lokalny projekt kodu.

Dalsze kroki