Дата публикации
ai_products

MCP‑приложения с интерактивным UI на Azure App Service: как собрать и развернуть за 10 минут

Что нового

Microsoft предлагает хостить MCP Apps — веб‑приложения с интерактивным интерфейсом для ИИ‑чатов — на Azure App Service.

Ключевые новшества:

  • MCP Apps как расширение Model Context Protocol:
    • Инструменты (tools) теперь могут возвращать не только JSON, но и богатый UI, который рендерится прямо в чате.
    • Поддерживаются клиенты: Claude Desktop, ChatGPT, VS Code Copilot, Goose, Postman и другие MCP‑совместимые клиенты.
  • Единый UI для разных клиентов:
    • Один и тот же HTML/JS/CSS‑интерфейс работает во всех поддерживаемых клиентах.
    • MCP Apps — это обычные веб‑приложения, которые отдаются через MCP.
  • Готовый пример:
    • Полноценный образец MCP‑приложения «виджет погоды».
    • ASP.NET Core — сервер MCP.
    • Vite + TypeScript — фронтенд, собираемый в один index.html.
    • Весь стек разворачивается на Azure App Service за один запуск azd up.
  • Интеграция с Azure App Service:
    • Always On — без cold start, UI отдается сразу.
    • Easy Auth с Entra ID — защита MCP‑эндпойнта без дополнительного кода.
    • Пользовательские домены и TLS — MCP‑сервер с вашим доменом и управляемыми сертификатами.
    • Deployment slots — поэтапные выкаты без простоя.
    • Sidecar‑контейнеры — Redis, очереди, мониторинг рядом с MCP‑сервером.
    • Application Insights — телеметрия по вызовам инструментов и UI.
  • Два варианта хостинга MCP Apps:
    • Azure Functions — serverless‑режим с масштабированием до нуля.
    • Azure App Service — постоянный хостинг без cold start и с «тяжелыми» продакшн‑фичами.

Цифр по производительности и цене в материале нет, но есть четкая связка: serverless‑экономика у Functions, всегда включенный продакшн‑хостинг у App Service.

Как это работает

MCP Apps: что это технически

MCP Apps расширяют Model Context Protocol так:

  1. Tool объявляет UI‑ресурс:
    • В метаданных инструмента появляется поле _meta.ui.resourceUri.
    • Пример: "ui://weather/index.html".
  2. Хост MCP запрашивает UI:
    • Когда клиент (например, VS Code Copilot) вызывает инструмент, хост MCP:
      • выполняет этот инструмент;
      • по resourceUri запрашивает UI‑ресурс у MCP‑сервера.
  3. Клиент рендерит UI в iframe:
    • UI загружается в изолированный iframe внутри чата.
    • Внутри iframe TypeScript‑приложение общается с хостом через postMessage через SDK @modelcontextprotocol/ext-apps.

По факту MCP App — это обычный веб‑фронтенд, упакованный в один HTML‑файл и выдаваемый как MCP‑ресурс с особым MIME‑типом.

Архитектура примера «виджет погоды»

Структура репозитория:

app-service-mcp-app-sample/
├── src/
│   ├── Program.cs              # Настройка MCP-сервера на ASP.NET Core
│   ├── WeatherTool.cs          # MCP-инструмент с описанием UI
│   ├── WeatherUIResource.cs    # MCP-ресурс, который отдает HTML
│   ├── WeatherService.cs       # Работа с Open-Meteo API
│   └── app/                    # Фронтенд на Vite (виджет погоды)
│       └── src/
│           └── weather-app.ts  # Интеграция с MCP Apps SDK
├── .vscode/
│   └── mcp.json                # Конфиг MCP-сервера для VS Code
├── azure.yaml                  # Конфиг Azure Developer CLI
└── infra/                      # Bicep-инфраструктура
``

#### MCP‑сервер: Program.cs

ASP.NET Core‑приложение поднимает MCP‑сервер и регистрирует инструменты и ресурсы:

```csharp
using ModelContextProtocol;

var builder = WebApplication.CreateBuilder(args);

// Register WeatherService
builder.Services.AddSingleton<WeatherService>(sp =>
    new WeatherService(WeatherService.CreateDefaultClient()));

// Add MCP Server with HTTP transport, tools, and resources
builder.Services.AddMcpServer()
    .WithHttpTransport(t => t.Stateless = true)
    .WithTools<WeatherTool>()
    .WithResources<WeatherUIResource>();

var app = builder.Build();

// Map MCP endpoints (no auth required for this sample)
app.MapMcp("/mcp").AllowAnonymous();

app.Run();

Что важно под капотом:

  • AddMcpServer() — регистрирует обработчик MCP‑протокола.
  • WithHttpTransport(t => t.Stateless = true) — включает HTTP‑транспорт в статeless‑режиме, без хранения сессий.
  • WithTools<WeatherTool>() — регистрирует MCP‑инструмент.
  • WithResources<WeatherUIResource>() — регистрирует UI‑ресурс.
  • MapMcp("/mcp") — MCP‑эндпойнт по пути /mcp.

Инструмент с UI‑метаданными: WeatherTool.cs

Инструмент объявляет resourceUri в метаданных через атрибут McpMeta:

using System.ComponentModel;
using ModelContextProtocol.Server;

[McpServerToolType]
public class WeatherTool
{
    private readonly WeatherService _weatherService;

    public WeatherTool(WeatherService weatherService)
    {
        _weatherService = weatherService;
    }

    [McpServerTool]
    [Description("Get current weather for a location via Open-Meteo. Returns weather data that displays in an interactive widget.")]
    [McpMeta("ui", JsonValue = """{"resourceUri": "ui://weather/index.html"}""")]
    public async Task<object> GetWeather(
        [Description("City name to check weather for (e.g., Seattle, New York, Miami)")]
        string location)
    {
        var result = await _weatherService.GetCurrentWeatherAsync(location);
        return result;
    }
}

Ключевая строка:

[McpMeta("ui", JsonValue = """{"resourceUri": "ui://weather/index.html"}""")]

Она добавляет в описание инструмента блок _meta.ui.resourceUri, на который ориентируется MCP‑хост. Когда ИИ‑клиент вызывает GetWeather, хост берет ui://weather/index.html и запрашивает соответствующий ресурс.

UI‑ресурс: WeatherUIResource.cs

Этот класс отдает собранный index.html как MCP‑ресурс с нужным MIME‑типом:

using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;

[McpServerResourceType]
public class WeatherUIResource
{
    [McpServerResource(
        UriTemplate = "ui://weather/index.html",
        Name = "weather_ui",
        MimeType = "text/html;profile=mcp-app")]
    public static ResourceContents GetWeatherUI()
    {
        var filePath = Path.Combine(
            AppContext.BaseDirectory, "app", "dist", "index.html");
        var html = File.ReadAllText(filePath);

        return new TextResourceContents
        {
            Uri = "ui://weather/index.html",
            MimeType = "text/html;profile=mcp-app",
            Text = html
        };
    }
}

Важно:

  • URI‑схема ui:// — для UI‑ресурсов MCP Apps.
  • MIME‑тип text/html;profile=mcp-app — сигнал клиенту MCP, что это MCP App.
  • Файл берется из app/dist/index.html — это результат сборки Vite.

Логика погоды: WeatherService.cs

WeatherService использует Open‑Meteo API:

  • геокодирует название города;
  • запрашивает текущие погодные данные;
  • возвращает результат в виде объекта, который потом получает UI.

Это обычный HTTP‑клиент на .NET, без специфики MCP.

Фронтенд MCP App: Vite + SDK

Фронтенд живет в src/app и собирается Vite в один HTML‑файл. Взаимодействие с MCP‑хостом — через SDK @modelcontextprotocol/ext-apps:

import { App } from "@modelcontextprotocol/ext-apps";

const app = new App({ name: "Weather Widget", version: "1.0.0" });

// Handle tool results from the server
app.ontoolresult = (params) => {
  const data = parseToolResultContent(params.content);
  if (data) render(data);
};

// Adapt to host theme (light/dark)
app.onhostcontextchanged = (ctx) => {
  if (ctx.theme) applyTheme(ctx.theme);
};

await app.connect();

Что делает SDK:

  • устанавливает соединение с хостом MCP через postMessage;
  • получает результаты вызова инструмента (ontoolresult);
  • реагирует на изменения контекста хоста (onhostcontextchanged) — например, смену темы.

Сборка Vite с vite-plugin-singlefile складывает HTML, JS и CSS в один index.html. Это удобно для MCP: UI отдается как один ресурс.

Почему Azure App Service подходит для MCP Apps

Технически App Service делает то, что MCP Apps требуют по максимуму:

  • Постоянный хостинг: .NET‑приложение с MCP‑сервером работает без остановки, UI‑ресурсы отдаются без задержек.
  • HTTP‑эндпойнт /mcp: MCP‑клиенты подключаются по HTTP, как к обычному веб‑сервису.
  • Интеграция с инфраструктурой Azure:
    • Entra ID для аутентификации;
    • слоты развертывания для безопасных обновлений;
    • sidecar‑контейнеры для Redis, очередей, агентов мониторинга;
    • Application Insights для логов и метрик вызовов MCP‑инструментов и UI.

Что это значит для вас

Когда использовать MCP Apps на Azure App Service

Этот стек полезен, если вы:

  • Строите сложные инструменты для ИИ‑клиентов:
    • дашборды аналитики;
    • визуализацию карт;
    • просмотрщики PDF и документов;
    • интерфейсы для управления системами.
  • Хотите, чтобы эти интерфейсы работали одинаково в Claude Desktop, ChatGPT, VS Code Copilot и других MCP‑клиентах.
  • Уже используете Azure и хотите развернуть MCP‑сервер рядом с другими сервисами.
  • Нуждаетесь в:
    • отсутствии cold start;
    • защищенных эндпойнтах с Entra ID;
    • продакшн‑процессах деплоя (слоты, мониторинг, домены).

Когда лучше Azure Functions, а не App Service

Microsoft предлагает простой ориентир:

Azure Functions — если вы:

  • пишете новое MCP‑приложение с нуля;
  • хотите serverless‑модель: масштабирование до нуля и оплата по вызовам;
  • можете терпеть возможный cold start (или готовы платить за Premium‑план для его снижения);
  • делаете event‑driven‑сценарии, где MCP — один из триггеров.

Azure App Service — если вы:

  • добавляете MCP‑функциональность к существующему веб‑приложению;
  • хотите всегда включенный сервер без cold start;
  • вам нужны постоянное состояние или интеграция с другими сервисами в рамках одного App Service;
  • планируете использовать Easy Auth, custom domains, deployment slots, sidecar‑контейнеры.

Таблично это выглядит так:

  • Масштабирование:
    • Functions: масштаб до нуля, оплата по запросам.
    • App Service: выделенный план, приложение всегда работает.
  • Cold start:
    • Functions: возможен (снижается Premium‑планом).
    • App Service: нет, при включенном Always On.
  • Деплой:
    • Functions: azd up с шаблоном Functions.
    • App Service: azd up с шаблоном App Service.
  • Специализация:
    • Functions: триггеры событий, durable‑функции.
    • App Service: Easy Auth, домены, слоты, sidecar‑сервисы.

Где это реально помогает

Конкретные сценарии:

  • Командные инструменты внутри компании:
    • Внутренний дашборд, который открывается прямо в ChatGPT или Copilot.
    • Безопасный доступ через Entra ID, без раздачи ключей и VPN‑доступа к базе.
  • Продукты для разработчиков:
    • Расширения для VS Code Copilot, которые показывают UI внутри чата.
    • Отладка и мониторинг сервисов через MCP‑инструменты.
  • Клиентские сервисы:
    • Виджеты погоды, курсов валют, аналитики, которые живут в чат‑клиентах.
    • Один код UI — сразу в нескольких ИИ‑клиентах.

Когда это не ваш вариант

  • Вам нужен простой текстовый инструмент без UI. В этом случае MCP Apps — лишний слой, достаточно обычного MCP‑инструмента.
  • Вы не хотите связываться с Azure, предпочитаете другой облачный провайдер или on‑prem.
  • У вас нет задач, где UI внутри ИИ‑чата дает выигрыш по UX.

Доступность из России

Azure и связанные сервисы, включая Azure App Service, официально ограничены для пользователей и компаний из России. Для работы может потребоваться зарубежный аккаунт, зарубежный способ оплаты и, в ряде случаев, VPN для доступа к порталу и API.

Если вы работаете из российской юрлицы, такой стек чаще всего подходит только для проектов, ориентированных на зарубежные рынки и инфраструктуру за пределами России.

Место на рынке

MCP Apps — это не модель и не облачный API, а способ встроить богатый UI в ИИ‑клиенты. Конкуренция здесь не между GPT‑5 и Claude 4, а между подходами к интеграции интерфейсов.

По сути, MCP Apps на Azure App Service конкурируют с:

  • собственными плагин‑системами отдельных ИИ‑клиентов;
  • кастомными веб‑панелями, которые пользователь открывает отдельно от чата;
  • serverless‑подходом на Azure Functions.

Что дает связка MCP Apps + Azure App Service:

  • Кросс‑клиентный UI: один интерфейс работает в Claude Desktop, ChatGPT, VS Code Copilot и других MCP‑клиентах.
  • Интеграция с Azure‑инфраструктурой: Entra ID, App Insights, deployment slots, sidecar‑сервисы.
  • Отсутствие cold start по сравнению с Functions в базовой конфигурации.

Чего нет:

  • Нет конкретных сравнений по скорости отклика или стоимости с другими облаками.
  • Нет прямых бенчмарков против альтернативных протоколов расширения.

Если вы уже глубоко сидите в Azure и строите инструменты вокруг Copilot, MCP Apps на App Service выглядят логичным продолжением этой экосистемы.

Установка

Для локального запуска понадобится:

  • .NET 9 SDK;
  • Node.js 18+;
  • Git и Azure Developer CLI (azd) для деплоя.

Клонирование и локальный запуск

# Clone the repo
git clone https://github.com/seligj95/app-service-mcp-app-sample.git
cd app-service-mcp-app-sample

# Build the frontend
cd src/app
npm install
npm run build

# Run the MCP server
cd ..
dotnet run

Сервер поднимется на http://localhost:5000.

Подключение к VS Code Copilot

В репозитории уже есть конфиг MCP‑сервера для VS Code:

{
  "servers": {
    "local-mcp-appservice": {
      "type": "http",
      "url": "http://localhost:5000/mcp"
    }
  }
}

Шаги:

  1. Откройте репозиторий в VS Code.
  2. Убедитесь, что файл .vscode/mcp.json на месте.
  3. Откройте панель GitHub Copilot Chat.
  4. Спросите: "What's the weather in Seattle?".

Copilot вызовет инструмент GetWeather, а виджет погоды отрендерится прямо в чате в виде интерактивного UI.

Как запустить на Azure App Service

Деплой через Azure Developer CLI

В корне репозитория уже лежат azure.yaml и Bicep‑шаблоны. Деплой сводится к одной команде:

cd app-service-mcp-app-sample
azd auth login
azd up

azd up сделает следующее:

  • создаст App Service Plan и Web App в вашей подписке Azure;
  • соберет .NET‑приложение и фронтенд на Vite;
  • задеплоит приложение на Azure App Service;
  • выведет публичный URL MCP‑эндпойнта.

После деплоя вы увидите адрес вида:

https://app-abc123.azurewebsites.net

Подключение удаленного MCP‑сервера

Обновите .vscode/mcp.json, чтобы подключаться к удаленному серверу:

{
  "servers": {
    "remote-weather-app": {
      "type": "http",
      "url": "https://app-abc123.azurewebsites.net/mcp"
    }
  }
}

Теперь ваш MCP App живет в облаке. Любой клиент, который поддерживает MCP Apps, может вызывать инструмент погоды и рендерить интерактивный виджет, не полагаясь на локальный сервер разработчика.

Что попробовать дальше

Если вы уже собрали пример с погодой, логичный следующий шаг — адаптировать его под свои задачи:

  • Прочитать спецификацию MCP Apps и добавить:
    • формы ввода;
    • сохранение состояния;
    • многошаговые сценарии.
  • Посмотреть примеры ext-apps на GitHub:
    • просмотр карт;
    • рендеринг PDF;
    • системные мониторы и другие UI.
  • Попробовать quickstart для MCP Apps на Azure Functions, если хотите serverless‑подход.
  • Изучить паттерны хостинга удаленных MCP‑серверов на App Service и добавить:
    • Easy Auth с Entra ID;
    • App Insights для телеметрии;
    • домены и TLS;
    • deployment slots для blue/green‑релизов.

Если вы делаете сложные инструменты вокруг ИИ‑чатов и уже используете Azure, MCP Apps на App Service дают понятный путь от прототипа до продакшна с минимальным количеством обвязки вокруг UI и инфраструктуры.


Читайте также

MCP‑приложения с интерактивным UI на Azure App Service: как собрать и развернуть за 10 минут — VogueTech | VogueTech