Freigeben über


Schnellstart: Erstellen eines benutzerdefinierten MCP-Remoteservers mit Azure Functions

In dieser Schnellstartanleitung erstellen Sie einen benutzerdefinierten MCP-Server (Remote Model Context Protocol) aus einem Vorlagenprojekt mithilfe der Azure Developer CLI (azd). Der MCP-Server verwendet die MCP-Servererweiterung Azure Functions, um Tools für KI-Modelle, Agents und Assistenten bereitzustellen. Nachdem Sie das Projekt lokal ausgeführt und Ihren Code mithilfe von GitHub Copilot überprüft haben, stellen Sie es in einer neuen serverlosen Funktions-App in Azure Functions bereit, die den aktuellen bewährten Methoden für sichere und skalierbare Bereitstellungen folgt.

Tipp

Mit Funktionen können Sie auch ein vorhandenes MCP-Servercodeprojekt in einer Flex-Verbrauchsplan-App bereitstellen, ohne Änderungen an Ihrem Codeprojekt vornehmen zu müssen. Weitere Informationen finden Sie in der Schnellstartanleitung: Hosten vorhandener MCP-Server auf Azure Functions.

Da die neue App unter dem Flex-Verbrauch-Plan ausgeführt wird, der einem nutzungsbasierten Abrechnungsmodell folgt, fallen für die Durchführung dieser Schnellstarts geringe Kosten in Höhe von wenigen US-Cent oder weniger in Ihrem Azure-Konto an.

Von Bedeutung

Während das Erstellen benutzerdefinierter MCP-Server für alle Funktionen-Sprachen unterstützt wird, enthält dieses Schnellstartszenario derzeit nur Beispiele für C#, Python und TypeScript. Um diese Schnellstartanleitung abzuschließen, wählen Sie oben im Artikel eine dieser unterstützten Sprachen aus.

Dieser Artikel unterstützt Version 4 des Node.js Programmiermodells für Azure Functions.

Dieser Artikel unterstützt Version 2 des Python-Programmiermodells für Azure Functions.

Voraussetzungen

Initialisieren des Projekts

Verwenden Sie den azd init Befehl, um ein lokales Azure Functions-Codeprojekt aus einer Vorlage zu erstellen.

  1. Öffnen Sie in Visual Studio Code einen Ordner oder Arbeitsbereich, in dem Sie Ihr Projekt erstellen möchten.
  1. Führen Sie im Terminal den folgenden azd init Befehl aus:

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

    Mit diesem Befehl werden die Projektdateien aus dem Vorlagen-Repository abgerufen und das Projekt im aktuellen Ordner initialisiert. Das -e-Flag legt einen Namen für die aktuelle Umgebung fest. In azdder Umgebung wird ein eindeutiger Bereitstellungskontext für Ihre App verwaltet, und Sie können mehrere definieren. Sie wird auch im Namen der Ressourcengruppe verwendet, die Sie in Azure erstellen.

  1. Führen Sie in Ihrer lokalen Terminal- oder Eingabeaufforderung den folgenden azd init Befehl aus:

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

    Mit diesem Befehl werden die Projektdateien aus dem Vorlagen-Repository abgerufen und das Projekt im aktuellen Ordner initialisiert. Das -e-Flag legt einen Namen für die aktuelle Umgebung fest. In azdder Umgebung wird ein eindeutiger Bereitstellungskontext für Ihre App verwaltet, und Sie können mehrere definieren. Sie wird auch in Namen der Ressourcen verwendet, die Sie in Azure erstellen.

  1. Führen Sie in Ihrer lokalen Terminal- oder Eingabeaufforderung den folgenden azd init Befehl aus:

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

    Mit diesem Befehl werden die Projektdateien aus dem Vorlagen-Repository abgerufen und das Projekt im aktuellen Ordner initialisiert. Das -e-Flag legt einen Namen für die aktuelle Umgebung fest. In azdder Umgebung wird ein eindeutiger Bereitstellungskontext für Ihre App verwaltet, und Sie können mehrere definieren. Sie wird auch in Namen der Ressourcen verwendet, die Sie in Azure erstellen.

  1. Führen Sie in Ihrer lokalen Terminal- oder Eingabeaufforderung den folgenden azd init Befehl aus:

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

    Mit diesem Befehl werden die Projektdateien aus dem Vorlagen-Repository abgerufen und das Projekt im aktuellen Ordner initialisiert. Das -e-Flag legt einen Namen für die aktuelle Umgebung fest. In azdder Umgebung wird ein eindeutiger Bereitstellungskontext für Ihre App verwaltet, und Sie können mehrere definieren. Sie wird auch in Namen der Ressourcen verwendet, die Sie in Azure erstellen.

Starten des Speicher-Emulators

Verwenden Sie den Azurite-Emulator, um eine Azure Storage-Kontoverbindung zu simulieren, wenn Sie Ihr Codeprojekt lokal ausführen.

  1. Falls noch nicht geschehen, installieren Sie Azurite.

  2. Drücken Sie F1. Suchen Sie in der Befehlspalette nach dem Befehl, und führen Sie den Befehl Azurite: Start aus, um den lokalen Speicher-Emulator zu starten.

Lokales Ausführen des MCP-Servers

Visual Studio Code ist in Azure Functions Core-Tools integriert, damit Sie dieses Projekt mithilfe des Azurite-Emulators auf Ihrem lokalen Entwicklungscomputer ausführen können.

  1. Um die Funktion lokal zu starten, drücken Sie F5, oder klicken Sie auf der Aktivitätsleiste auf der linken Seite auf das Symbol Ausführen und debuggen. Im Terminalbereich wird die Ausgabe aus den Core Tools angezeigt. Ihre App wird im Terminalbereich gestartet, und Sie können den Namen der Funktionen sehen, die lokal ausgeführt werden.

  2. Notieren Sie sich den lokalen MCP-Serverendpunkt, z. B. http://localhost:7071/runtime/webhooks/mcp, den Sie zum Konfigurieren von GitHub Copilot in Visual Studio Code verwenden.

Verifizieren mit GitHub Copilot

Um Ihren Code zu überprüfen, fügen Sie das ausgeführte Projekt als MCP-Server für GitHub Copilot in Visual Studio Code hinzu:

  1. Drücken Sie F1. In der Befehlspalette suchen und MCP: Add Server ausführen.

  2. Wählen Sie HTTP (Server-Sent Ereignisse) als Übertragungstyp.

  3. Geben Sie die URL des MCP-Endpunkts ein, den Sie im vorherigen Schritt kopiert haben.

  4. Verwenden Sie die generierte Server-ID , und wählen Sie "Arbeitsbereich" aus, um die MCP-Serververbindung in Ihren Arbeitsbereichseinstellungen zu speichern.

  5. Öffnen Sie die Befehlspalette, und führen Sie MCP aus: Listenserver auf, und stellen Sie sicher, dass der hinzugefügte Server aufgelistet und ausgeführt wird.

  6. Wählen Sie im Copilot-Chat den Agentmodus aus, und führen Sie diese Eingabeaufforderung aus:

    Say Hello
    

    Wenn Sie zum Ausführen des Tools aufgefordert werden, wählen Sie "In diesem Arbeitsbereich zulassen " aus, damit Sie die Berechtigung nicht beibehalten müssen. Die Eingabeaufforderung wird ausgeführt und gibt eine Hello World Antwort zurück. Die Funktionsausführungsinformationen werden in die Protokolle geschrieben.

  7. Wählen Sie nun code in einer Ihrer Projektdateien aus, und führen Sie diese Eingabeaufforderung aus:

    Save this snippet as snippet1
    

    Copilot speichert den Codeausschnitt und antwortet auf Ihre Anforderung mit Informationen zum Abrufen des Codeausschnitts mithilfe des getSnippets Tools. Auch hier können Sie die Funktionsausführung in den Protokollen überprüfen und überprüfen, ob die saveSnippets Funktion ausgeführt wurde.

  8. Führen Sie im Copilot-Chat diese Eingabeaufforderung aus:

    Retrieve snippet1 and apply to NewFile
    

    Copilot ruft die Codeausschnitte ab, fügt sie zu einer Datei namens NewFile hinzu und unternimmt alle notwendigen Schritte, um den Codeausschnitt in Ihrem Projekt funktionsfähig zu machen. Die Funktionsprotokolle zeigen, dass der getSnippets Endpunkt aufgerufen wurde.

  9. Wenn Sie mit dem Testen fertig sind, drücken Sie STRG+C, um den Funktionshost anzuhalten.

Überprüfen des Codes (optional)

Sie können den Code überprüfen, der die MCP-Servertools definiert:

Der Funktionscode für die MCP-Servertools wird im src Ordner definiert. Das McpToolTrigger Attribut macht die Funktionen als MCP-Servertools verfügbar:

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

Sie können die vollständige Projektvorlage im GitHub-Repository von Azure Functions .NET MCP Server anzeigen.

Der Funktionscode für die MCP-Servertools wird im src/main/java/com/function/ Ordner definiert. Die @McpToolTrigger Anmerkung macht die Funktionen als MCP-Servertools verfügbar:

            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

Sie können die vollständige Projektvorlage im GitHub-Repository von Azure Functions Java MCP Server anzeigen.

Der Funktionscode für die MCP-Servertools wird in der src/function_app.py Datei definiert. Die MCP-Funktionsanmerkungen machen diese Funktionen als MCP-Servertools verfügbar:

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"

Sie können die vollständige Projektvorlage im GitHub-Repository von Azure Functions Python MCP Server anzeigen.

Der Funktionscode für die MCP-Servertools wird im src Ordner definiert. Die MCP-Funktionsregistrierung macht diese Funktionen als MCP-Servertools verfügbar:

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

Sie können die vollständige Projektvorlage im GitHub-Repository von Azure Functions TypeScript MCP Server anzeigen.

Nachdem Sie die MCP-Servertools lokal überprüft haben, können Sie das Projekt in Azure veröffentlichen.

In Azure bereitstellen

Dieses Projekt ist so konfiguriert, dass der azd up-Befehl verwendet wird, um dieses Projekt in einer neuen Funktions-App in einem Flex-Verbrauchsplan in Azure bereitzustellen. Dieses Projekt enthält eine Reihe von Bicep-Dateien, die azd verwendet, um eine sichere Bereitstellung für einen Flex-Verbrauch-Plan zu erstellen, was bewährten Methoden entspricht.

  1. Drücken Sie in Visual Studio Code F1, um die Befehlspalette zu öffnen. Suchen und ausführen Sie den Befehl Azure Developer CLI (azd): Package, Provison and Deploy (up). Melden Sie sich dann mit Ihrem Azure-Konto an.

  2. Wenn Sie noch nicht angemeldet sind, authentifizieren Sie sich mit Ihrem Azure-Konto.

  3. Wenn Sie dazu aufgefordert werden, stellen Sie die folgenden erforderlichen Bereitstellungsparameter bereit:

    Parameter Description
    Azure-Abonnement Das Abonnement, in dem Ihre Ressourcen erstellt werden.
    Azure-Standort Die Azure-Region, in der die Ressourcengruppe erstellt werden soll, die die neuen Azure-Ressourcen enthält. Es werden nur Regionen angezeigt, die den Flex-Verbrauchsplan derzeit unterstützen.

    Nachdem der Befehl erfolgreich abgeschlossen wurde, werden Links zu den von Ihnen erstellten Ressourcen angezeigt.

Verbinden mit Ihrem Remote-MCP-Server

Ihr MCP-Server wird jetzt in Azure ausgeführt. Wenn Sie auf die Tools zugreifen, müssen Sie einen Systemschlüssel in Ihre Anforderung einschließen. Dieser Schlüssel bietet eine Gewisse Zugriffssteuerung für Clients, die auf Ihren Remote-MCP-Server zugreifen. Nachdem Sie diesen Schlüssel erhalten haben, können Sie GitHub Copilot mit Ihrem Remoteserver verbinden.

  1. Führen Sie dieses Skript aus, das azd und die Azure CLI verwendet, um sowohl die MCP-Server-URL als auch den Systemschlüssel (mcp_extension) auszugeben, die für den Zugriff auf die Tools erforderlich sind.

    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. Drücken Sie in Visual Studio Code F1 , um die Befehlspalette zu öffnen, den Befehl MCP: Open Workspace Folder MCP Configuratonzu suchen und auszuführen, der die mcp.json Konfigurationsdatei öffnet.

  3. Suchen Sie in der mcp.json Konfiguration den benannten MCP-Server, den Sie zuvor hinzugefügt haben, ändern Sie den url Wert in Die URL des Remote-MCP-Servers, und fügen Sie ein headers.x-functions-key Element hinzu, das Ihren kopierten MCP-Serverzugriffsschlüssel enthält, wie im folgenden Beispiel gezeigt:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Wählen Sie die Schaltfläche "Start " oberhalb des Servernamens im geöffneten Bereich mcp.json aus, um den Remote-MCP-Server neu zu starten, diesmal mit Ihrer bereitgestellten App.

Überprüfen Sie Ihre Bereitstellung

Sie können jetzt GitHub Copilot nutzen, um Ihre MCP-Remotetools genauso wie lokal zu verwenden; jedoch wird der Code jetzt sicher in Azure ausgeführt. Wiederholen Sie die gleichen Befehle, die Sie zuvor verwendet haben, um sicherzustellen, dass alles ordnungsgemäß funktioniert.

Bereinigen von Ressourcen

Wenn Sie mit ihrem MCP-Server und den zugehörigen Ressourcen fertig sind, verwenden Sie diesen Befehl, um die Funktions-App und die zugehörigen Ressourcen aus Azure zu löschen, um weitere Kosten zu vermeiden:

azd down --no-prompt

Hinweis

Die --no-prompt-Option weist azd an, Ihre Ressourcengruppe zu löschen, ohne Ihre Bestätigung. Dieser Befehl wirkt sich nicht auf Ihr lokales Codeprojekt aus.

Nächste Schritte