Partager via


Démarrage rapide : Créer un serveur MCP distant personnalisé à l’aide d’Azure Functions

Dans ce guide de démarrage rapide, vous allez créer un serveur MCP (Remote Model Context Protocol) personnalisé à partir d’un projet de modèle à l’aide d’Azure Developer CLI (azd). Le serveur MCP utilise l’extension de serveur MCP Azure Functions pour fournir des outils pour les modèles, agents et assistants IA. Après avoir exécuté le projet localement et vérifié votre code à l’aide de GitHub Copilot, vous le déployez sur une nouvelle application de fonction serverless dans Azure Functions qui suit les meilleures pratiques actuelles pour les déploiements sécurisés et évolutifs.

Conseil / Astuce

Functions vous permet également de déployer un projet de code de serveur MCP existant dans une application de plan Flex Consumption sans avoir à apporter de modifications à votre projet de code. Pour plus d’informations, consultez Démarrage rapide : Héberger des serveurs MCP existants sur Azure Functions.

Étant donné que la nouvelle application s’exécute sur le plan Flex Consumption, qui suit un modèle de facturation basé sur le paiement à l'utilisation, suivre ce guide de démarrage rapide entraîne un léger coût de quelques cents USD ou moins sur votre compte Azure.

Important

Bien que la création de serveurs MCP personnalisés soit prise en charge pour tous les langages Functions, ce scénario de démarrage rapide ne contient actuellement que des exemples pour C#, Python et TypeScript. Pour suivre ce guide de démarrage rapide, sélectionnez l’une de ces langues prises en charge en haut de l’article.

Cet article prend en charge la version 4 du modèle de programmation Node.js pour Azure Functions.

Cet article prend en charge la version 2 du modèle de programmation Python pour Azure Functions.

Prerequisites

Initialiser le projet

Utilisez la azd init commande pour créer un projet de code Azure Functions local à partir d’un modèle.

  1. Dans Visual Studio Code, ouvrez un dossier ou un espace de travail dans lequel vous souhaitez créer votre projet.
  1. Dans le terminal, exécutez cette azd init commande :

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

    Cette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur -e définit un nom pour l’environnement actuel. Dans azd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Il est également utilisé dans le nom du groupe de ressources que vous créez dans Azure.

  1. Dans votre terminal local ou invite de commandes, exécutez cette azd init commande :

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

    Cette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur -e définit un nom pour l’environnement actuel. Dans azd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Il est également utilisé dans les noms des ressources que vous créez dans Azure.

  1. Dans votre terminal local ou invite de commandes, exécutez cette azd init commande :

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

    Cette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur -e définit un nom pour l’environnement actuel. Dans azd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Il est également utilisé dans les noms des ressources que vous créez dans Azure.

  1. Dans votre terminal local ou invite de commandes, exécutez cette azd init commande :

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

    Cette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur -e définit un nom pour l’environnement actuel. Dans azd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Il est également utilisé dans les noms des ressources que vous créez dans Azure.

Démarrer l’émulateur de stockage

Utilisez l’émulateur Azurite pour simuler une connexion de compte de stockage Azure lors de l’exécution locale de votre projet de code.

  1. Si ce n’est déjà fait, installez Azurite.

  2. Appuyez sur F1. Dans la palette de commandes, recherchez et exécutez la commande Azurite: Start pour démarrer l’émulateur de stockage local.

Exécuter votre serveur MCP localement

Visual Studio Code s’intègre aux outils Azure Functions Core pour vous permettre d’exécuter ce projet sur votre ordinateur de développement local à l’aide de l’émulateur Azurite.

  1. Pour démarrer la fonction localement, appuyez sur F5 ou cliquez sur l’icône Exécuter et déboguer dans la barre d’activité de gauche. Le panneau Terminal affiche la sortie des outils principaux. Votre application démarre dans le panneau Terminal et vous pouvez voir le nom des fonctions qui s’exécutent localement.

  2. Faites une note du point de terminaison du serveur MCP local (par exemple http://localhost:7071/runtime/webhooks/mcp), que vous utilisez pour configurer GitHub Copilot dans Visual Studio Code.

Vérifier à l’aide de GitHub Copilot

Pour vérifier votre code, ajoutez le projet en cours d’exécution en tant que serveur MCP pour GitHub Copilot dans Visual Studio Code :

  1. Appuyez sur F1. Dans la palette de commandes, recherchez et exécutez MCP : Ajouter un serveur.

  2. Choisissez HTTP (Server-Sent Events) pour le type de transport.

  3. Entrez l’URL du point de terminaison MCP que vous avez copié à l’étape précédente.

  4. Utilisez l’ID de serveur généré et sélectionnez Espace de travail pour enregistrer la connexion du serveur MCP à vos paramètres d’espace de travail.

  5. Ouvrez la palette de commandes et exécutez MCP : Répertorier les serveurs et vérifiez que le serveur que vous avez ajouté est répertorié et en cours d’exécution.

  6. Dans la conversation Copilot, sélectionnez le mode Agent et exécutez cette invite :

    Say Hello
    

    Lorsque vous êtes invité à exécuter l’outil, sélectionnez Autoriser dans cet espace de travail afin de ne pas avoir à accorder l’autorisation. La requête s’exécute et retourne une réponse Hello Worldet les informations d’exécution de la fonction sont écrites dans les journaux.

  7. À présent, sélectionnez du code dans l’un de vos fichiers de projet et exécutez cette invite :

    Save this snippet as snippet1
    

    Copilot stocke l’extrait de code et répond à votre demande avec des informations sur la façon de récupérer l’extrait à l’aide de l’outil getSnippets . Encore une fois, vous pouvez passer en revue l’exécution de la fonction dans les journaux et vérifier que la fonction saveSnippets s’est exécutée.

  8. Dans la conversation Copilot, exécutez cette instruction :

    Retrieve snippet1 and apply to NewFile
    

    Copilot récupère les extraits de code, l’ajoute à un fichier appelé NewFileet fait tout ce qu’il pense être nécessaire pour que l’extrait de code fonctionne dans votre projet. Les journaux Functions indiquent que le point de terminaison getSnippets a été appelé.

  9. Lorsque vous avez terminé le test, appuyez sur Ctrl+C pour arrêter l’hôte Functions.

Examiner le code (facultatif)

Vous pouvez consulter le code qui définit les outils serveur MCP :

Le code de fonction des outils serveur MCP est défini dans le src dossier. L’attribut McpToolTrigger expose les fonctions en tant qu’outils MCP Server :

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

Vous pouvez afficher le modèle de projet complet dans le dépôt GitHub du serveur .NET MCP Azure Functions .

Le code de fonction des outils serveur MCP est défini dans le src/main/java/com/function/ dossier. L’annotation @McpToolTrigger expose les fonctions en tant qu’outils de serveur 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

Vous pouvez afficher le modèle de projet complet dans le référentiel GitHub du serveur MCP Java Azure Functions .

Le code de fonction des outils serveur MCP est défini dans le src/function_app.py fichier. Les annotations de fonction MCP exposent ces fonctions en tant qu’outils de serveur 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"

Vous pouvez afficher le modèle de projet complet dans le référentiel GitHub du Azure Functions Python MCP Server.

Le code de fonction des outils serveur MCP est défini dans le src dossier. L’inscription de la fonction MCP expose ces fonctions en tant qu’outils de serveur 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;
}

Vous pouvez afficher le modèle de projet complet dans le référentiel GitHub du serveur MCP Azure Functions TypeScript .

Après avoir vérifié les outils de serveur MCP localement, vous pouvez publier le projet sur Azure.

Déployer sur Azure

Ce projet est configuré pour utiliser la commande azd up visant à déployer ce projet dans une nouvelle application de fonction dans un plan Consommation flexible dans Azure. Ce projet comprend un ensemble de fichiers Bicep que azd utile pour créer un déploiement sécurisé dans un plan Consommation flexible qui suit les meilleures pratiques.

  1. Dans Visual Studio Code, appuyez sur F1 pour ouvrir la palette de commandes. Recherchez et exécutez la commande Azure Developer CLI (azd): Package, Provison and Deploy (up). Ensuite, connectez-vous à l’aide de votre compte Azure.

  2. Si vous n’êtes pas encore connecté, authentifiez-vous auprès de votre compte Azure.

  3. Lorsque vous y êtes invité, fournissez ces paramètres de déploiement requis :

    Paramètre Descriptif
    Abonnement Azure Abonnement dans lequel vos ressources sont créées.
    Emplacement Azure Région Azure dans laquelle créer le groupe de ressources qui contient les nouvelles ressources Azure. Seules sont montrées les régions qui prennent actuellement en charge le plan Consommation flexible.

    Une fois la commande terminée, vous voyez des liens vers les ressources que vous avez créées.

Se connecter à votre serveur MCP distant

Votre serveur MCP s’exécute désormais dans Azure. Lorsque vous accédez aux outils, vous devez inclure une clé système dans votre demande. Cette clé fournit un degré de contrôle d’accès pour les clients qui accèdent à votre serveur MCP distant. Après avoir obtenu cette clé, vous pouvez connecter GitHub Copilot à votre serveur distant.

  1. Exécutez ce script qui utilise azd et Azure CLI pour imprimer à la fois l’URL du serveur MCP et la clé système (mcp_extension) requise pour accéder aux outils :

    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. Dans Visual Studio Code, appuyez sur F1 pour ouvrir la palette de commandes, recherchez et exécutez la commande MCP: Open Workspace Folder MCP Configuraton, ce qui ouvre le mcp.json fichier de configuration.

  3. Dans la mcp.json configuration, recherchez le serveur MCP nommé que vous avez ajouté précédemment, remplacez la valeur par l’URL url de votre serveur MCP distant et ajoutez un headers.x-functions-key élément, qui contient votre clé d’accès au serveur MCP copiée, comme dans cet exemple :

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Sélectionnez le bouton Démarrer au-dessus du nom de votre serveur dans l’ouverture mcp.json pour redémarrer le serveur MCP distant, cette fois à l’aide de votre application déployée.

Vérifier votre déploiement

Vous pouvez maintenant avoir GitHub Copilot utiliser vos outils MCP distants comme vous l’avez fait localement, mais maintenant le code s’exécute en toute sécurité dans Azure. Relisez les mêmes commandes que celles que vous avez utilisées précédemment pour vous assurer que tout fonctionne correctement.

Nettoyer les ressources

Lorsque vous avez terminé d’utiliser votre serveur MCP et vos ressources associées, utilisez cette commande pour supprimer l’application de fonction et ses ressources associées d’Azure afin d’éviter les coûts supplémentaires :

azd down --no-prompt

Note

L’option --no-prompt indique azd de supprimer votre groupe de ressources sans confirmation de vous. Cette commande n’affecte pas votre projet de code local.

Étapes suivantes