Condividi tramite


Guida introduttiva: Creare un server MCP remoto personalizzato con Funzioni di Azure

In questa guida introduttiva si crea un server MCP (Remote Model Context Protocol) personalizzato da un progetto modello usando l'interfaccia della riga di comando per sviluppatori di Azure (azd). Il server MCP usa l'estensione server MCP di Funzioni di Azure per fornire strumenti per modelli di intelligenza artificiale, agenti e assistenti. Dopo aver eseguito il progetto in locale e aver verificato il codice usando GitHub Copilot, è possibile distribuirlo in una nuova app per le funzioni serverless in Funzioni di Azure che segue le procedure consigliate correnti per distribuzioni sicure e scalabili.

Suggerimento

Funzioni consente anche di distribuire un progetto di codice server MCP esistente in un'applicazione con piano Flex a consumo senza dover apportare modifiche al progetto di codice. Per altre informazioni, vedere Avvio rapido: Ospitare server MCP esistenti in Funzioni di Azure.

Poiché la nuova app viene eseguita nel piano a consumo Flex, che segue un modello di fatturazione paghi solo ciò che usi, il completamento di questo inizio rapido comporta un costo ridotto di pochi centesimi di dollaro o meno nell'account Azure.

Importante

La creazione di server MCP personalizzati è supportata in tutti i linguaggi delle funzioni; tuttavia, questo scenario di avvio rapido al momento include solo esempi per C#, Python e TypeScript. Per completare questa guida introduttiva, selezionare una di queste lingue supportate nella parte superiore dell'articolo.

Questo articolo supporta la versione 4 del modello di programmazione Node.js per Funzioni di Azure.

Questo articolo supporta la versione 2 del modello di programmazione Python per Funzioni di Azure.

Prerequisiti

  • .NET 8.0 SDK

Inizializzare il progetto

Usare il azd init comando per creare un progetto di codice di Funzioni di Azure locale da un modello.

  1. In Visual Studio Code aprire una cartella o un'area di lavoro in cui si vuole creare il progetto.
  1. Nel terminale eseguire questo azd init comando:

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

    Questo comando esegue il pull dei file di progetto dal repository dei modelli e inizializza il progetto nella cartella corrente. Il flag -e imposta un nome per l'ambiente corrente. In azdl'ambiente mantiene un contesto di distribuzione univoco per l'app ed è possibile definire più di uno. Viene usato anche nel nome del gruppo di risorse creato in Azure.

  1. Nel terminale locale o nel prompt dei comandi eseguire questo azd init comando:

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

    Questo comando esegue il pull dei file di progetto dal repository dei modelli e inizializza il progetto nella cartella corrente. Il flag -e imposta un nome per l'ambiente corrente. In azdl'ambiente mantiene un contesto di distribuzione univoco per l'app ed è possibile definire più di uno. Viene utilizzato anche nei nomi delle risorse che crei in Azure.

  1. Nel terminale locale o nel prompt dei comandi eseguire questo azd init comando:

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

    Questo comando esegue il pull dei file di progetto dal repository dei modelli e inizializza il progetto nella cartella corrente. Il flag -e imposta un nome per l'ambiente corrente. In azdl'ambiente mantiene un contesto di distribuzione univoco per l'app ed è possibile definire più di uno. Viene utilizzato anche nei nomi delle risorse che crei in Azure.

  1. Nel terminale locale o nel prompt dei comandi eseguire questo azd init comando:

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

    Questo comando esegue il pull dei file di progetto dal repository dei modelli e inizializza il progetto nella cartella corrente. Il flag -e imposta un nome per l'ambiente corrente. In azdl'ambiente mantiene un contesto di distribuzione univoco per l'app ed è possibile definire più di uno. Viene utilizzato anche nei nomi delle risorse che crei in Azure.

Avviare l'emulatore di archiviazione

Usare l'emulatore Azurite per simulare una connessione all'account di archiviazione di Azure durante l'esecuzione del progetto di codice in locale.

  1. Se non è già stato fatto, installare Azurite.

  2. Premere F1. Nel riquadro comandi cercare ed eseguire il comando Azurite: Start per avviare l'emulatore di archiviazione locale.

Eseguire il server MCP in locale

Visual Studio Code si integra con gli strumenti di base di Funzioni di Azure per consentire l'esecuzione di questo progetto nel computer di sviluppo locale usando l'emulatore Azurite.

  1. Per avviare la funzione in locale, premere F5 o l'icona Esegui e debug nella barra attività sul lato sinistro. Il pannello Terminale visualizza l'output di Core Tools. L'app viene avviata nel pannello Terminale ed è possibile visualizzare il nome delle funzioni in esecuzione in locale.

  2. Prendere nota dell'endpoint server MCP locale (ad esempio http://localhost:7071/runtime/webhooks/mcp), usato per configurare GitHub Copilot in Visual Studio Code.

Verificare l'uso di GitHub Copilot

Per verificare il codice, aggiungere il progetto in esecuzione come server MCP per GitHub Copilot in Visual Studio Code:

  1. Premere F1. Nel riquadro comandi cercare ed eseguire MCP: Aggiungi server.

  2. Scegliere HTTP (Eventi Inviati dal Server) per il tipo di trasporto.

  3. Immettere l'URL dell'endpoint MCP copiato nel passaggio precedente.

  4. Usare l'ID server generato e selezionare Area di lavoro per salvare la connessione del server MCP alle impostazioni dell'area di lavoro.

  5. Aprire il riquadro comandi ed eseguire MCP: Elencare i server e verificare che il server aggiunto sia elencato e in esecuzione.

  6. Nella chat di Copilot selezionare Modalità agente ed eseguire questo prompt:

    Say Hello
    

    Quando viene richiesto di eseguire lo strumento, selezionare Consenti in questa area di lavoro in modo da non dover continuare a concedere l'autorizzazione. Il prompt viene eseguito e restituisce una Hello World risposta e le informazioni sull'esecuzione della funzione vengono scritte nei log.

  7. Selezionare ora il codice in uno dei file di progetto ed eseguire questa richiesta:

    Save this snippet as snippet1
    

    Copilot archivia il frammento di codice e risponde alla richiesta con informazioni su come recuperare il frammento usando lo getSnippets strumento . Anche in questo caso, è possibile esaminare l'esecuzione della funzione nei log e verificare che la saveSnippets funzione sia stata eseguita.

  8. Nella chat di Copilot eseguire questa richiesta:

    Retrieve snippet1 and apply to NewFile
    

    Copilot recupera i frammenti di codice, lo aggiunge a un file denominato NewFileed esegue qualsiasi altra operazione necessaria per rendere il frammento di codice funzionante nel progetto. I log di Funzioni mostrano che l'endpoint getSnippets è stato chiamato.

  9. Alla fine dei test, premi Ctrl+C per arrestare l'host delle funzioni.

Esaminare il codice (facoltativo)

È possibile esaminare il codice che definisce gli strumenti server MCP:

Il codice della funzione per gli strumenti server MCP viene definito nella src cartella . L'attributo McpToolTrigger espone le funzioni come strumenti del server 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;
    }
}

È possibile visualizzare il modello di progetto completo nel repository GitHub del Azure Functions .NET MCP Server.

Il codice della funzione per gli strumenti server MCP viene definito nella src/main/java/com/function/ cartella . L'annotazione @McpToolTrigger espone le funzioni come strumenti del server 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

È possibile visualizzare il modello di progetto completo nel repository GitHub del MCP Server di Funzioni di Azure Java.

Il codice della funzione per gli strumenti server MCP viene definito nel src/function_app.py file . Le annotazioni della funzione MCP espongono queste funzioni come strumenti del server 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"

È possibile visualizzare il modello di progetto completo nel repository GitHub del Server MCP Python di Funzioni di Azure.

Il codice della funzione per gli strumenti server MCP viene definito nella src cartella . La registrazione della funzione MCP espone queste funzioni come strumenti del server 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;
}

È possibile visualizzare il modello di progetto completo nel repository GitHub del server TypeScript MCP di Azure Functions.

Dopo aver verificato gli strumenti server MCP in locale, è possibile pubblicare il progetto in Azure.

Distribuzione su Azure

Questo progetto è configurato per l'uso del comando azd up al fine di distribuire questo progetto in una nuova app per le funzioni in un piano a consumo Flex in Azure. Il progetto include un set di file Bicep che azd usa per creare una distribuzione sicura in un piano a consumo Flex che segue le procedure consigliate.

  1. In Visual Studio Code premere F1 per aprire il riquadro comandi. Cercare ed eseguire il comando Azure Developer CLI (azd): Package, Provison and Deploy (up). Accedere quindi usando l'account Azure.

  2. Se non è già stato eseguito l'accesso, eseguire l'autenticazione con l'account Azure.

  3. Quando richiesto, specificare questi parametri di distribuzione obbligatori:

    Parametro Description
    Sottoscrizione di Azure Sottoscrizione in cui vengono create le risorse.
    Località di Azure Area di Azure in cui creare il gruppo di risorse che contiene le nuove risorse di Azure. Vengono visualizzate solo le aree che attualmente supportano il piano a consumo Flex.

    Al termine del comando, vengono visualizzati i collegamenti alle risorse create.

Connettersi al server MCP remoto

Il server MCP è ora in esecuzione in Azure. Quando si accede agli strumenti, è necessario includere una chiave di sistema nella richiesta. Questa chiave fornisce un grado di controllo di accesso per i client che accedono al server MCP remoto. Dopo aver creato questa chiave, è possibile connettere GitHub Copilot al server remoto.

  1. Eseguire questo script che usa azd e l'interfaccia della riga di comando di Azure per stampare sia l'URL del server MCP che la chiave di sistema (mcp_extension) necessaria per accedere agli strumenti:

    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. In Visual Studio Code premere F1 per aprire il riquadro comandi, cercare ed eseguire il comando MCP: Open Workspace Folder MCP Configuraton, che apre il mcp.json file di configurazione.

  3. mcp.json Nella configurazione trovare il server MCP denominato aggiunto in precedenza, modificare il valore nell'URL url del server MCP remoto e aggiungere un headers.x-functions-key elemento contenente la chiave di accesso al server MCP copiata, come in questo esempio:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Selezionare il pulsante Start sopra il nome del server nell'area aperta mcp.json per riavviare il server MCP remoto, questa volta usando l'app distribuita.

Verificare la distribuzione

È ora possibile usare GitHub Copilot con gli strumenti MCP remoti come in locale, ma ora il codice viene eseguito in modo sicuro in Azure. Riprodurre gli stessi comandi usati in precedenza per assicurarsi che tutto funzioni correttamente.

Pulire le risorse

Al termine dell'uso del server MCP e delle risorse correlate, usare questo comando per eliminare l'app per le funzioni e le relative risorse da Azure per evitare di incorrere in ulteriori costi:

azd down --no-prompt

Annotazioni

L'opzione --no-prompt indica azd di eliminare il gruppo di risorse senza conferma. Questo comando non influisce sul progetto di codice locale.

Passaggi successivi