Partilhar via


Guia de início rápido: criar um servidor MCP remoto personalizado usando o Azure Functions

Neste início rápido, você cria um servidor MCP (Model Context Protocol) remoto personalizado a partir de um projeto de modelo usando a CLI do Desenvolvedor do Azure (azd). O servidor MCP usa a extensão de servidor MCP do Azure Functions para fornecer ferramentas para modelos, agentes e assistentes de IA. Depois de executar o projeto localmente e verificar seu código usando o GitHub Copilot, você o implanta em um novo aplicativo de função sem servidor no Azure Functions que segue as práticas recomendadas atuais para implantações seguras e escaláveis.

Sugestão

O Functions também permite implementar um projeto de código de servidor MCP existente para uma aplicação de plano Flex Consumption sem ter de fazer alterações ao seu projeto de código. Para mais informações, consulte Quickstart: Alojar servidores MCP existentes no Azure Functions.

Como o novo aplicativo é executado no plano Flex Consumption, que segue um modelo de cobrança de pagamento pelo que você usa , concluir este início rápido incorre em um pequeno custo de alguns centavos de dólar ou menos em sua conta do Azure.

Importante

Embora a criação de servidores MCP personalizados seja suportada para todas as linguagens de Funções, este cenário de início rápido atualmente só tem exemplos para C#, Python e TypeScript. Para completar este quickstart, selecione uma destas línguas suportadas no topo do artigo.

Este artigo suporta a versão 4 do modelo de programação Node.js para o Azure Functions.

Este artigo suporta a versão 2 do modelo de programação Python para o Azure Functions.

Pré-requisitos

Inicializar o projeto

Use o azd init comando para criar um projeto de código local do Azure Functions a partir de um modelo.

  1. No Visual Studio Code, abra uma pasta ou espaço de trabalho onde você deseja criar seu projeto.
  1. No Terminal, execute este azd init comando:

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

    Este comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O -e sinalizador define um nome para o ambiente atual. No azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. Ele também é usado no nome do grupo de recursos que você cria no Azure.

  1. No terminal local ou prompt de comando, execute este azd init comando:

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

    Este comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O -e sinalizador define um nome para o ambiente atual. No azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. Também é usado nos nomes dos recursos que crias no Azure.

  1. No terminal local ou prompt de comando, execute este azd init comando:

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

    Este comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O -e sinalizador define um nome para o ambiente atual. No azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. Também é usado nos nomes dos recursos que crias no Azure.

  1. No terminal local ou prompt de comando, execute este azd init comando:

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

    Este comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O -e sinalizador define um nome para o ambiente atual. No azd, o ambiente mantém um contexto de implantação exclusivo para seu aplicativo e você pode definir mais de um. Também é usado nos nomes dos recursos que crias no Azure.

Inicie o emulador de armazenamento

Use o emulador Azurite para simular uma ligação à conta Azure Storage ao executar o seu projeto de código localmente.

  1. Se ainda não o fez, instale o Azurite.

  2. Pressione F1. Na paleta de comandos, procure e execute o comando Azurite: Start para iniciar o emulador de armazenamento local.

Execute o servidor MCP localmente

O Visual Studio Code integra-se com as ferramentas principais do Azure Functions para permitir que você execute esse projeto em seu computador de desenvolvimento local usando o emulador Azurite.

  1. Para iniciar a função localmente, pressione F5 ou o ícone Executar e Depurar na barra de atividades do lado esquerdo. O painel Terminal exibe a saída das Ferramentas Principais. Seu aplicativo é iniciado no painel Terminal e você pode ver o nome das funções que estão sendo executadas localmente.

  2. Anote o ponto de extremidade do servidor MCP local (como http://localhost:7071/runtime/webhooks/mcp), que você usa para configurar o GitHub Copilot no Visual Studio Code.

Verificar usando o GitHub Copilot

Para verificar seu código, adicione o projeto em execução como um servidor MCP para o Copilot do GitHub no Visual Studio Code:

  1. Pressione F1. Na paleta de comandos, procure e execute MCP: Add Server.

  2. Escolha HTTP (Eventos Enviados pelo Servidor) para o tipo de transporte.

  3. Insira a URL do ponto de extremidade MCP copiado na etapa anterior.

  4. Use a ID do servidor gerada e selecione Espaço de trabalho para salvar a conexão do servidor MCP nas configurações do espaço de trabalho.

  5. Abra a paleta de comandos e execute MCP: List Servers e verifique se o servidor adicionado está listado e em execução.

  6. No chat do Copilot, selecione o Modo de agente e execute o prompt:

    Say Hello
    

    Quando solicitado a executar a ferramenta, selecione Permitir neste espaço de trabalho para que você não precise continuar concedendo permissão. O prompt é acionado e retorna uma resposta, e as informações de execução da função são escritas nos logs.

  7. Agora, selecione algum código em um dos seus arquivos de projeto e execute este prompt:

    Save this snippet as snippet1
    

    O Copilot armazena o trecho e responde à sua solicitação com informações sobre como recuperá-lo usando a getSnippets ferramenta. Novamente, você pode revisar a execução da função nos logs e verificar se a saveSnippets função foi executada.

  8. Na conversa do Copilot, execute este comando:

    Retrieve snippet1 and apply to NewFile
    

    O Copilot recupera os trechos, adiciona-os a um arquivo chamado NewFile, e faz o que mais achar necessário para fazer o trecho de código funcionar em seu projeto. Os Logs de Funções mostram que o endpoint getSnippets foi chamado.

  9. Quando terminar o teste, pressione Ctrl+C para parar o host do Functions.

Rever o código (opcional)

Você pode revisar o código que define as ferramentas de servidor MCP:

O código de função para as ferramentas de servidor MCP é definido na src pasta. O McpToolTrigger atributo expõe as funções como ferramentas do 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;
    }
}

Você pode exibir o modelo de projeto completo no repositório GitHub do Servidor MCP .NET do Azure Functions .

O código de função para as ferramentas de servidor MCP é definido na src/main/java/com/function/ pasta. A @McpToolTrigger anotação expõe as funções como ferramentas do MCP Server:

            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

Você pode exibir o modelo de projeto completo no repositório GitHub do Servidor Java MCP do Azure Functions .

O código de função para as ferramentas de servidor MCP é definido no src/function_app.py arquivo. As anotações de função MCP expõem essas funções como ferramentas do Servidor 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"

Você pode exibir o modelo de projeto completo no repositório GitHub do Servidor MCP Python do Azure Functions .

O código de função para as ferramentas de servidor MCP é definido na src pasta. O registro da função MCP expõe essas funções como ferramentas do MCP Server:

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

Você pode exibir o modelo de projeto completo no repositório GitHub do Azure Functions TypeScript MCP Server .

Depois de verificar as ferramentas do servidor MCP localmente, você pode publicar o projeto no Azure.

Publicar no Azure

Este projeto está configurado para usar o azd up comando para implantar esse projeto em um novo aplicativo de função em um plano de Consumo Flex no Azure. O projeto inclui um conjunto de arquivos Bicep que azd utiliza para criar uma implementação segura num plano de consumo Flex que segue as melhores práticas.

  1. No Visual Studio Code, pressione F1 para abrir a paleta de comandos. Procure e execute o comando Azure Developer CLI (azd): Package, Provison and Deploy (up). Em seguida, entre usando sua conta do Azure.

  2. Se ainda não tiver sessão iniciada, autentique-se com a sua conta do Azure.

  3. Quando solicitado, forneça estes parâmetros de implantação necessários:

    Parâmetro Description
    Subscrição do Azure Subscrição na qual os seus recursos são criados.
    Localização do Azure Região do Azure na qual criar o grupo de recursos que contém os novos recursos do Azure. Apenas as regiões que atualmente suportam o plano Flex Consumption são mostradas.

    Depois que o comando for concluído com êxito, você verá links para os recursos criados.

Conecte-se ao seu servidor MCP remoto

Seu servidor MCP agora está em execução no Azure. Ao acessar as ferramentas, você precisa incluir uma chave do sistema em sua solicitação. Essa chave fornece um grau de controle de acesso para clientes que acessam seu servidor MCP remoto. Depois de obter essa chave, você pode conectar o GitHub Copilot ao seu servidor remoto.

  1. Execute este script que usa azd a CLI do Azure para imprimir a URL do servidor MCP e a chave do sistema (mcp_extension) necessária para acessar as ferramentas:

    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. No Visual Studio Code, pressione F1 para abrir a paleta de comandos, procurar e executar o comando MCP: Open Workspace Folder MCP Configuraton, que abre o mcp.json arquivo de configuração.

  3. Na configuração mcp.json, localize o servidor MCP nomeado que adicionou anteriormente, altere o valor do url para a URL do servidor MCP remoto e adicione um elemento headers.x-functions-key que contém a chave de acesso do servidor MCP que copiou, como neste exemplo:

    {
        "servers": {
            "remote-mcp-function": {
                "type": "http",
                "url": "https://contoso.azurewebsites.net/runtime/webhooks/mcp",
                "headers": {
                    "x-functions-key": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u..."
                }
            }
        }
    }
    
  4. Selecione o botão Iniciar acima do nome do servidor em aberto mcp.json para reiniciar o servidor MCP remoto, desta vez usando seu aplicativo implantado.

Verificar a sua implantação

Agora você pode fazer com que o GitHub Copilot use suas ferramentas MCP remotas da mesma forma que fazia localmente, mas agora o código é executado com segurança no Azure. Repita os mesmos comandos usados anteriormente para garantir que tudo funcione corretamente.

Limpeza de recursos

Quando terminar de trabalhar com seu servidor MCP e recursos relacionados, use este comando para excluir o aplicativo de função e seus recursos relacionados do Azure para evitar incorrer em custos adicionais:

azd down --no-prompt

Observação

A opção --no-prompt instrui o azd a excluir o seu grupo de recursos sem a sua confirmação. Este comando não afeta seu projeto de código local.

Próximos passos