Quickstart: Construa uma Aplicação MCP usando Funções do Azure

Neste início rápido, cria uma aplicação Model Context Protocol (MCP) a partir de um projeto modelo construído usando a extensão Funções do Azure MCP. As aplicações MCP são servidores MCP com ferramentas que devolvem resultados em interfaces de utilizador ricas e interativas em vez de texto. Implementa a aplicação usando a CLI de Desenvolvedor Azure (azd). Também pode usar a extensão Funções do Azure MCP para criar servidores MCP que tenham ferramentas baseadas em texto.

Depois de executar o projeto localmente e verificar o seu código usando o GitHub Copilot, implementa-o numa nova aplicação serverless function no Funções do Azure que segue as melhores práticas atuais para implementações seguras e escaláveis.

Captura de ecrã da interface de uma aplicação meteorológica para Seattle mostrando garoa, temperatura, humidade, vento e hora do relatório.

Como a nova aplicação funciona com o plano Flex Consumption, que segue um modelo de faturação em que se "paga pelo que se usa", completar este início rápido acarreta um pequeno custo de alguns cêntimos ou menos na sua conta Azure.

Importante

Embora creating MCP Apps seja suportado para JavaScript, este quickstart atualmente só tem exemplos para C#, Java, Python e TypeScript. Para completar este quickstart, selecione uma destas línguas suportadas no topo do artigo.

Importante

Atualmente, a extensão MCP não oferece suporte a aplicativos do PowerShell.

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

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

Pré-requisitos

Inicializar o projeto

Use a CLI do Azure Developer para criar um projeto de código Funções do Azure a partir de um template.

  1. No Visual Studio Code, abre uma pasta ou espaço de trabalho onde queres criar o teu projeto.
  1. Execute o seguinte comando no Terminal:

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

    Este comando retira os ficheiros do projeto do repositório template e inicializa o projeto na pasta atual. A bandeira -e 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. Pressiona F1 para abrir a paleta de comandos. Procure e execute Azure Developer CLI (azd): init.

  2. Quando solicitado, selecione Selecionar um modelo.

  1. Procure e selecione Funções MCP Remotas com TypeScript.

  2. Quando solicitado, introduza mcpweather-ts como nome do ambiente.

    O comando retira os ficheiros do projeto do repositório template e inicializa o projeto na pasta 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. Procure e selecione Remote MCP Functions com Python.

  2. Quando solicitado, introduza mcpweather-python como nome do ambiente.

    O comando retira os ficheiros do projeto do repositório template e inicializa o projeto na pasta 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. Pesquise por e selecione Funções MCP Remotas com Java.

  2. Quando solicitado, introduza mcpweather-java como nome do ambiente.

    O comando retira os ficheiros do projeto do repositório template e inicializa o projeto na pasta 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 do Armazenamento do Azure 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.

Constrói a interface de aplicações MCP

A ferramenta meteorológica MCP Apps inclui uma aplicação frontend que deve construir antes de executar o projeto.

  1. No terminal, vai à pasta da aplicação UI e constrói a aplicação:

    cd src/McpWeatherApp/app
    npm install
    npm run build
    cd ../
    
  1. No terminal, vai à pasta da aplicação UI e constrói a aplicação:

    cd samples/McpWeatherApp/app
    npm install
    npm run build
    cd ..
    
  1. No terminal, vai à pasta da aplicação UI e constrói a aplicação:

    cd src/app
    npm install
    npm run build
    cd ..
    
  2. No src diretório, crie um ambiente virtual para executar a aplicação:

    python -m venv .venv
    
  1. No terminal, vai à pasta da aplicação UI e constrói a aplicação:

    cd src/app
    npm install
    npm run build
    cd ../..
    

Execute o servidor MCP localmente

Quando solicitado, selecione src/McpWeatherApp. Vê este prompt porque há dois projetos na solução, e o outro projeto não é utilizado neste artigo.

Numa janela de terminal, certifica-te de que estás na samples/McpWeatherApp pasta do projeto.

Visual Studio Code integra-se com Funções do Azure Core tools para permitir que execute este projeto no seu computador local de desenvolvimento. Para iniciar a sua aplicação de Funções localmente, pressione F5 ou selecione o ícone Executar e Depurar na barra de Atividades do lado esquerdo.

O painel Terminal exibe a saída das Ferramentas Principais. A tua aplicação começa no painel de Terminais , e podes ver os nomes das funções a correr localmente.

Verifica usando o GitHub Copilot

O modelo do projeto inclui um .vscode/mcp.json ficheiro que define um local-mcp-function servidor que aponta para o seu endpoint MCP local. Use esta configuração para verificar o seu código usando o GitHub Copilot no Visual Studio Code:

  1. Abra o .vscode/mcp.json ficheiro e selecione o botão Start acima da local-mcp-function configuração.

  2. Na janela Copilot Chat, certifique-se de que o modo Agent está selecionado, selecione o ícone Configurar ferramentas e verifique se o MCP Server:local-mcp-function está ativado no chat.

  3. Executa este prompt:

    What's the weather in Seattle?
    

    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 executa a GetWeather ferramenta, que devolve dados meteorológicos. Como esta ferramenta declara os metadados da interface, o host MCP também recupera o recurso da interface e renderiza um widget meteorológico interativo num iframe sandbox dentro do chat.

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

Rever o código (opcional)

Pode rever o código que define as ferramentas MCP Apps. Uma ferramenta MCP Apps requer dois componentes:

  • Uma ferramenta com metadados de UI que declara uma ui.resourceUri referência para um recurso de UI.
  • Um recurso que disponibiliza o HTML/JavaScript agrupado no URI correspondente ui:// .

O código de função da ferramenta meteorológica MCP Apps está definido na src/McpWeatherApp pasta. Nesta função, o [McpMetadata] atributo adiciona metadados da interface à GetWeather ferramenta.

[Function(nameof(GetWeather))]
public async Task<object> GetWeather(
    [McpToolTrigger(nameof(GetWeather), "Returns current weather for a location via Open-Meteo.")]
    [McpMetadata(ToolMetadata)]
        ToolInvocationContext context,
    [McpToolProperty("location", "City name to check weather for (e.g., Seattle, New York, Miami)")]
        string location)
{
    try
    {
        var result = await _weatherService.GetCurrentWeatherAsync(location);
        
        if (result is WeatherResult weather)
        {
            _logger.LogInformation("Weather fetched for {Location}: {TempC}°C", weather.Location, weather.TemperatureC);
        }
        else if (result is WeatherError error)
        {
            _logger.LogWarning("Weather error for {Location}: {Error}", error.Location, error.Error);
        }

        return result;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Failed to get weather for {Location}", location);
        return new WeatherError(location ?? "Unknown", $"Unable to fetch weather: {ex.Message}", "api.open-meteo.com");
    }
}

O [McpResourceTrigger] atributo é aplicado à GetWeatherWidget função, que serve o widget HTML.

[Function(nameof(GetWeatherWidget))]
public string GetWeatherWidget(
    [McpResourceTrigger(
        "ui://weather/index.html",
        "Weather Widget",
        MimeType = "text/html;profile=mcp-app",
        Description = "Interactive weather display for MCP Apps")]
    [McpMetadata(ResourceMetadata)]
        ResourceInvocationContext context)
{
    var file = Path.Combine(AppContext.BaseDirectory, "app", "dist", "index.html");
    return File.ReadAllText(file);
}

A constante ToolMetadata declara uma ui.resourceUri que instrui o host MCP a obter a UI interativa de ui://weather/index.html após a execução da ferramenta.

private const string ToolMetadata = """
    {
        "ui": {
            "resourceUri": "ui://weather/index.html"
        }
    }
    """;

A GetWeatherWidget função serve o ficheiro HTML incluído nesse URI usando [McpResourceTrigger].

Pode ver o modelo completo do projeto no repositório Funções do Azure .NET MCP Server GitHub.

O código de função para a ferramenta meteorológica MCP Apps está definido no src/McpWeatherApp/function_app.py ficheiro. Nesta função, o metadata parâmetro em @app.mcp_tool() adiciona metadados da interface à get_weather ferramenta.

# Get Weather Tool - returns current weather for a location
@app.mcp_tool(metadata=TOOL_METADATA)
@app.mcp_tool_property(arg_name="location", description="City name to check weather for (e.g., Seattle, New York, Miami)")
def get_weather(location: str) -> Dict[str, Any]:
    """Returns current weather for a location via Open-Meteo."""
    logging.info(f"Getting weather for location: {location}")
    
    try:
        result = weather_service.get_current_weather(location)
        
        if "TemperatureC" in result:
            logging.info(f"Weather fetched for {result['Location']}: {result['TemperatureC']}°C")
        else:
            logging.warning(f"Weather error for {result['Location']}: {result.get('Error', 'Unknown error')}")
        
        return json.dumps(result)
    except Exception as e:
        logging.error(f"Failed to get weather for {location}: {e}")
        return json.dumps({
            "Location": location or "Unknown",
            "Error": f"Unable to fetch weather: {str(e)}",
            "Source": "api.open-meteo.com"
        })

O @app.mcp_resource_trigger() decorador é aplicado à get_weather_widget função, que serve o widget HTML.

@app.mcp_resource_trigger(
    arg_name="context",
    uri=WEATHER_WIDGET_URI,
    resource_name=WEATHER_WIDGET_NAME,
    description=WEATHER_WIDGET_DESCRIPTION,
    mime_type=WEATHER_WIDGET_MIME_TYPE,
    metadata=RESOURCE_METADATA
)
def get_weather_widget(context) -> str:
    """Get the weather widget HTML content."""
    logging.info("Getting weather widget")
    
    try:
        # Get the path to the widget HTML file
        # Current file is src/function_app.py, look for src/app/index.html
        current_dir = Path(__file__).parent
        file_path = current_dir / "app" / "dist" / "index.html"
        
        if file_path.exists():
            return file_path.read_text(encoding="utf-8")
        else:
            logging.warning(f"Weather widget file not found at: {file_path}")
            # Return a fallback HTML if file not found
            return """<!DOCTYPE html>
<html>
<head><title>Weather Widget</title></head>
<body>
  <h1>Weather Widget</h1>
  <p>Widget content not found. Please ensure the app/index.html file exists.</p>
</body>
</html>"""
    except Exception as e:
        logging.error(f"Error reading weather widget file: {e}")
        return """<!DOCTYPE html>
<html>
<head><title>Weather Widget Error</title></head>
<body>
  <h1>Weather Widget</h1>
  <p>Error loading widget content.</p>
</body>
</html>"""

A constante TOOL_METADATA declara uma ui.resourceUri que instrui o host MCP a obter a UI interativa de ui://weather/index.html após a execução da ferramenta.

TOOL_METADATA = json.dumps({"ui": {"resourceUri": "ui://weather/index.html"}})

A get_weather_widget função serve o ficheiro HTML incluído nesse URI usando @app.mcp_resource_trigger().

Pode ver o modelo completo do projeto no repositório Funções do Azure Python MCP Server GitHub.

O código de função para a ferramenta meteorológica MCP Apps está definido no src/functions/weatherMcpApp.ts ficheiro. Nesta função, a propriedade metadata em app.mcpTool() adiciona metadados de interface do utilizador à ferramenta getWeather quando esta é registada.

O getWeather handler recolhe dados meteorológicos para uma localização e devolve-os como JSON.

A app.mcpResource() função regista o getWeatherWidget handler, que serve o widget HTML.

O getWeatherWidget handler lê e devolve o ficheiro HTML incluído.

A constante TOOL_METADATA declara uma ui.resourceUri que instrui o host MCP a obter a UI interativa de ui://weather/index.html após a execução da ferramenta.

Pode ver o modelo completo do projeto no repositório Funções do Azure TypeScript MCP Server GitHub.

O código de função da ferramenta meteorológica MCP Apps está definido na samples/McpWeatherApp pasta. Nesta função, a @McpMetadata anotação adiciona metadados da interface à GetWeather ferramenta.

@FunctionName("GetWeather")
public String getWeather(
        @McpToolTrigger(
                name = "GetWeather",
                description = "Returns current weather for a location via Open-Meteo.")
        @McpMetadata(
                name = "GetWeather",
                json = TOOL_METADATA)
        String context,
        @McpToolProperty(
                name = "location",
                propertyType = "string",
                description = "City name to check weather for (e.g., Seattle, New York, Miami)")
        String location,
        final ExecutionContext executionContext) {

    executionContext.getLogger().info("GetWeather: looking up weather for '" + location + "'");

    Object result = weatherService.getCurrentWeather(location);

    if (result instanceof WeatherResult weather) {
        executionContext.getLogger().info("Weather fetched for " + weather.getLocation()
                + ": " + weather.getTemperatureC() + "°C");
    } else if (result instanceof WeatherError error) {
        executionContext.getLogger().warning("Weather error for " + error.getLocation()
                + ": " + error.getError());
    }

    try {
        return MAPPER.writeValueAsString(result);
    } catch (Exception e) {
        executionContext.getLogger().log(Level.SEVERE, "Failed to serialize weather result", e);
        return "{\"error\": \"Serialization failed\"}";
    }
}

A @McpResourceTrigger anotação é aplicada à GetWeatherWidget função, que serve o widget HTML.

@FunctionName("GetWeatherWidget")
public String getWeatherWidget(
        @McpResourceTrigger(
                name = "context",
                uri = "ui://weather/index.html",
                resourceName = "Weather Widget",
                title = "Weather Widget",
                description = "Interactive weather display for MCP Apps",
                mimeType = "text/html;profile=mcp-app")
        @McpMetadata(
                name = "context",
                json = RESOURCE_METADATA)
        String context,
        final ExecutionContext executionContext) {

A constante TOOL_METADATA declara uma ui.resourceUri que instrui o host MCP a obter a UI interativa de ui://weather/index.html após a execução da ferramenta.

private static final String TOOL_METADATA = """
        {
            "ui": {
                "resourceUri": "ui://weather/index.html"
            }
        }
        """;

A GetWeatherWidget função serve o ficheiro HTML incluído nesse URI usando @McpResourceTrigger.

Pode ver o modelo completo do projeto no repositório Funções do Azure Java MCP Server GitHub.

Depois de verificar localmente as ferramentas MCP Apps, pode publicar o projeto no Azure.

Implementar no Azure

Este projeto está configurado para usar azd para implementar este projeto numa nova aplicação funcional, num plano Flex Consumption em Azure. O projeto inclui um conjunto de ficheiros Bicep que azd utiliza para criar uma implementação segura num plano Flex Consumption que segue as melhores práticas.

  1. Em Visual Studio Code, pressione F1 para abrir a paleta de comandos. Procura e executa o comando Azure Developer CLI (azd): Package, Provision and Deploy (up). Depois, inicia sessão usando a tua conta Azure.

  2. Quando solicitado, selecione estes parâmetros de implementação obrigatórios:

    Parâmetro Description
    Subscrição do Azure Subscrição na qual os seus recursos são criados.
    Localização Azure Região do Azure onde 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.
    vnetEnabled False para evitar a criação de recursos de rede virtual, o que simplifica a implementação.

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

Este projeto está configurado para usar azd para implementar este projeto numa nova aplicação funcional, num plano Flex Consumption em Azure. O projeto inclui um conjunto de ficheiros Bicep que azd utiliza para criar uma implementação segura num plano Flex Consumption que segue as melhores práticas.

  1. No Terminal, execute este azd env set comando:

    azd env set DEPLOY_SERVICE weather 
    

    Este comando define a DEPLOY_SERVICE variável para provisionar weather recursos relacionados com a aplicação

  2. Execute o azd provision comando e forneça os parâmetros necessários para fornecer recursos:

    azd provision
    
    Parâmetro Description
    Subscrição do Azure Subscrição na qual os seus recursos são criados.
    Localização Azure Região do Azure onde 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.
    vnetEnabled False para evitar a criação de recursos de rede virtual, o que simplifica a implementação.

    Quando solicitado, escolha a sua subscrição, uma região Azure para os recursos e escolha false para evitar a criação de recursos de rede virtual e assim simplificar a implementação.

  3. Execute o comando azd deploy para implementar a aplicação weather para Azure:

    azd deploy --service weather
    

Conecte-se ao seu servidor MCP remoto

O seu servidor MCP está agora a correr no Azure. O modelo de projeto inclui uma remote-mcp-function entrada .vscode/mcp.json que já está configurada para se ligar ao seu servidor remoto. Quando inicia este servidor, o VS Code solicita-lhe o nome da aplicação de função e a chave de sistema necessária para aceder ao endpoint MCP remoto.

  1. Execute este script que utiliza azd e o CLI do Azure para imprimir tanto o nome da aplicação de função como a chave de sistema (mcp_extension) necessária para aceder às 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 "Function app name: %s\n" "$SERVICE_API_NAME"
    printf "MCP Server key: %s\n" "$MCP_EXTENSION_KEY"
    
  2. Em .vscode/mcp.json, selecione Start acima da remote-mcp-function configuração.

  3. Quando solicitado, introduza o nome da função da aplicação e os valores-chave do sistema do passo anterior.

Verifique a sua implementação

Agora podes fazer com que o GitHub Copilot use as tuas ferramentas MCP remotas tal como fizeste localmente, mas agora o código corre de forma segura no Azure. Repita os mesmos comandos usados anteriormente para garantir que tudo funcione corretamente.

Limpeza de recursos

Quando terminar de trabalhar com o seu servidor MCP e recursos relacionados, use este comando para eliminar a aplicação de funções e os seus recursos relacionados do Azure, evitando custos adicionais:

azd down 

Próximos passos