Compartilhar via


Início Rápido: Criar um servidor MCP remoto personalizado usando o Azure Functions

Neste início rápido, você criará um servidor MCP (Protocolo de Contexto de Modelo) 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 de IA, agentes e assistentes. Depois de executar o projeto localmente e verificar seu código usando o GitHub Copilot, você o implanta em um novo aplicativo de funções sem servidor no Azure Functions que segue as práticas recomendadas atuais para implantações seguras e escalonáveis.

Dica

O Functions também permite implantar um projeto de código de servidor MCP existente em um aplicativo de plano de consumo flex sem precisar fazer alterações no projeto de código. Para obter mais informações, consulte Início Rápido: Hospedar servidores MCP existentes no Azure Functions.

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

Importante

Embora haja suporte para a criação de servidores MCP personalizados para todos os idiomas do Functions, este cenário de início rápido atualmente tem apenas exemplos para C#, Python e TypeScript. Para concluir este início rápido, selecione um desses idiomas com suporte na parte superior do artigo.

Este artigo dá suporte à versão 4 do modelo de programação Node.js para o Azure Functions.

Este artigo dá suporte à versão 2 do modelo de programação do 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 workspace em que você deseja criar seu projeto.
  1. No Terminal, execute este azd init comando:

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

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

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

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

    Esse comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O sinalizador -e define um nome para o ambiente atual. Em 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 em nomes dos recursos que você cria no Azure.

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

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

    Esse comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O sinalizador -e define um nome para o ambiente atual. Em 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 em nomes dos recursos que você cria no Azure.

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

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

    Esse comando extrai os arquivos de projeto do repositório de modelos e inicializa o projeto na pasta atual. O sinalizador -e define um nome para o ambiente atual. Em 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 em nomes dos recursos que você cria no Azure.

Iniciar o emulador de armazenamento

Use o emulador do Azurite para simular uma conexão de conta de Armazenamento do Azure ao executar seu projeto de código localmente.

  1. Caso ainda não tenha feito isso, instale o Azurite.

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

Executar o servidor MCP localmente

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

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

  2. Anote o endpoint 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 GitHub Copilot no Visual Studio Code:

  1. Pressione F1. Na paleta de comandos, pesquise e execute MCP: Adicionar Servidor.

  2. Escolha HTTP (Server-Sent Events) para o tipo de transporte.

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

  4. Use o ID do Servidor gerado e selecione Workspace para salvar a conexão do servidor MCP nas configurações da Área de Trabalho.

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

  6. No chat do Copilot, selecione o modo agente e execute este prompt:

    Say Hello
    

    Quando solicitado a executar a ferramenta, selecione Permitir nesta Área de Trabalho para que você não precise continuar concedendo permissão. O prompt é executado e retorna uma Hello World resposta e as informações de execução de função são gravadas nos logs.

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

    Save this snippet as snippet1
    

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

  8. No Copilot Chat, utilize este prompt:

    Retrieve snippet1 and apply to NewFile
    

    Copilot recupera os snippets, adiciona-os a um arquivo chamado NewFilee faz o que achar necessário para fazer o snippet de código funcionar em seu projeto. Os logs de Funções mostram que o endpoint getSnippets foi chamado.

  9. Quando terminar de testar, pressione Ctrl+C para interromper o host do Functions.

Examinar o código (opcional)

Você pode examinar o código que define as ferramentas do servidor MCP:

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

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

O código de função para as ferramentas do servidor MCP é definido na src/main/java/com/function/ pasta. A @McpToolTrigger anotação expõe as funções como ferramentas do SERVIDOR 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

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 do servidor MCP é definido no src/function_app.py arquivo. As anotações da 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 visualizar o modelo de projeto completo no repositório GitHub do Azure Functions Python MCP Server.

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

Você pode visualizar 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 comando azd up para implantar este projeto em um novo aplicativo de funções em um plano de Consumo Flex no Azure. O projeto inclui um conjunto de arquivos Bicep que azd usa para criar uma implantação segura em um plano de Consumo Flexível que segue as melhores práticas.

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

  2. Se você ainda não estiver conectado, autentique-se com sua conta do Azure.

  3. Quando solicitado, forneça esses parâmetros de implantação obrigatórios:

    Parâmetro Description
    Assinatura do Azure Assinatura na qual seus recursos serã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. Somente regiões que atualmente dão suporte para o plano de Consumo Flex são mostradas.

    Após o comando ser concluído com sucesso, você verá links para os recursos que criou.

Conectar-se ao servidor MCP remoto

Seu servidor MCP agora está em execução no Azure. Quando você acessa as ferramentas, 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 servidor remoto.

  1. Execute este script que usa azd e 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, pesquise e execute o comando MCP: Open Workspace Folder MCP Configuraton, que abre o mcp.json arquivo de configuração.

  3. mcp.json Na configuração, localize o servidor MCP nomeado que você adicionou anteriormente, altere o url valor para a URL do servidor MCP remoto e adicione um headers.x-functions-key elemento, que contém a chave de acesso do servidor MCP copiada, 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 ao abrir mcp.json para reiniciar o servidor MCP remoto, desta vez usando seu aplicativo implantado.

Verificar sua implantação

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

Limpar os recursos

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

azd down --no-prompt

Observação

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

Próximas etapas