Compartir vía


Compilación de un agente openAI de .NET mediante un servidor MCP en Azure Container Apps

En este artículo se muestra cómo crear un agente de Protocolo de contexto de modelo (MCP) mediante .NET. En este ejemplo, el cliente MCP (escrito en C#/.NET) se conecta a un servidor MCP (escrito en TypeScript) para administrar una lista de tareas pendientes. El cliente busca herramientas disponibles desde el servidor y las envía a un modelo de Azure OpenAI. A continuación, los usuarios pueden comunicarse con el sistema de tareas pendientes mediante el idioma diario.

Obtener al código

Consulte la plantilla OpenAI MCP Agent Building Block AI. En este ejemplo se muestra cómo compilar un agente de OpenAI que usa un cliente MCP para consumir un servidor MCP existente.

Vaya a la sección de tutorial de código para comprender cómo funciona este ejemplo.

Introducción a la arquitectura

En el diagrama siguiente se muestra la arquitectura sencilla de la aplicación de ejemplo: diagrama que muestra la arquitectura de Visual Studio Code que hospeda el agente y el cliente MCP en el servidor MCP.

  • Cliente MCP: se conecta al servidor MCP y encuentra las herramientas disponibles.
  • Cliente de chat: funciona con Azure OpenAI para comprender el lenguaje natural
  • Interfaz de usuario de Blazor: proporciona una interfaz web donde los usuarios pueden chatear
  • Capa de transporte: usa eventos de Server-Sent (SSE) para enviar mensajes en tiempo real
  • Autenticación: usa tokens JWT para mantener la conexión segura

El servidor MCP se ejecuta como una aplicación en contenedores en Azure Container Apps (ACA). Usa un back-end de TypeScript para proporcionar herramientas al cliente MCP a través del protocolo de contexto de modelo. Todas las herramientas funcionan con una base de datos SQLite de back-end.

Nota:

Visite Compilación de un servidor MCP de TypeScript mediante Azure Container Apps para ver el tutorial de código del servidor MCP de TypeScript que se usa en este artículo.

Cost

Para mantener bajos los costos, en este ejemplo se usan planes de tarifa básicos o de consumo para la mayoría de los recursos. Ajuste el nivel según sea necesario y elimine los recursos cuando haya terminado para evitar cargos.

Prerrequisitos

Un contenedor de desarrollo incluye todas las dependencias que necesita para este artículo. Puede ejecutarlo en GitHub Codespaces (en un explorador) o localmente mediante Visual Studio Code.

Para seguir este artículo, asegúrese de cumplir estos requisitos previos:

Implementación de un modelo gpt-5-mini de AI Foundry mediante la extensión de VS Code de AI Foundry

Implemente un gpt-5-mini modelo mediante la extensión AI Foundry en Visual Studio Code mediante los pasos siguientes:

Creación de un proyecto de AI Foundry e implementación del modelo

Creación de la cadena de conexión del modelo openAI

  1. Una vez implementado el gpt-5-mini modelo, haga clic con el botón derecho en el modelo en la extensión AI Foundry y seleccione Copiar clave de API para copiar la clave de API del modelo en el Portapapeles.

  2. A continuación, haga clic con el botón derecho en el modelo implementado gpt-5-mini en la extensión AI Foundry y seleccione Copiar punto de conexión para copiar el punto de conexión del modelo en el Portapapeles, como se muestra en la captura de pantalla siguiente:

    Captura de pantalla que muestra el menú contextual del modelo implementado con las opciones Copiar punto de conexión y Copiar clave de API resaltadas.

  3. Por último, cree una cadena de conexión para el modelo implementado gpt-5-mini mediante el punto de conexión copiado y la clave de API con el siguiente formato: Endpoint=<AZURE_OPENAI_ENDPOINT>;Key=<AZURE_OPENAI_API_KEY>. Necesitará esta cadena de conexión más adelante en el artículo.

Entorno de desarrollo abierto

Siga estos pasos para configurar un entorno de desarrollo preconfigurado con todas las dependencias necesarias.

GitHub Codespaces ejecuta un contenedor de desarrollo administrado por GitHub con Visual Studio Code para web como interfaz. Use GitHub Codespaces para la configuración más sencilla, ya que incluye las herramientas y dependencias necesarias preinstaladas para este artículo.

Importante

Todas las cuentas de GitHub pueden usar Codespaces durante un máximo de 60 horas gratis cada mes con dos instancias principales. Para obtener más información, consulte GitHub Codespaces mensualmente incluido el almacenamiento y las horas principales.

Siga estos pasos para crear un nuevo espacio de código de GitHub en la main rama del Azure-Samples/openai-mcp-agent-dotnet repositorio de GitHub.

  1. Haga clic con el botón derecho en el botón siguiente y seleccione Abrir vínculo en la nueva ventana. Esta acción le permite tener el entorno de desarrollo y la documentación abierta en paralelo.

    Abrir en GitHub Codespaces

  2. En la página Crear espacio de códigos , revise y seleccione Crear nuevo espacio de código.

  3. Espere a que se inicie el espacio de código. Puede tardar unos minutos.

  4. Asegúrese de que el nombre del modelo implementado es gpt-5-mini. Si el modelo implementado es diferente, actualice src/McpTodo.ClientApp/appsettings.json con el nombre de implementación correcto.

    {
      "OpenAI": {
        // Make sure this is the right deployment name.
        "DeploymentName": "gpt-5-mini"
      }
    }
    
  5. Inicie sesión en Azure con la CLI para desarrolladores de Azure en el terminal de la parte inferior de la pantalla.

    azd auth login
    
  6. Copie el código del terminal y péguelo en un explorador. Siga las instrucciones para autenticarse con su cuenta de Azure.

Realiza el resto de las tareas de este contenedor de desarrollo.

Nota:

Para ejecutar el agente MCP localmente:

  1. Configure el entorno como se describe en la sección Introducción del repositorio de ejemplo.
  2. Instale el servidor MCP siguiendo las instrucciones de la sección Get MCP Server App del repositorio de ejemplo.
  3. Ejecute el agente MCP localmente siguiendo las instrucciones de la sección Ejecutar localmente en el repositorio de ejemplo.
  4. Vaya a la sección Use the TODO MCP agent (Usar el agente MCP de TODO ) para continuar.

Implementación y ejecución

El repositorio de ejemplo contiene todos los archivos de código y configuración para la implementación de Azure del agente MCP. Los pasos siguientes le guiarán por el proceso de implementación de Azure del agente MCP de ejemplo.

Implementación en Azure

Importante

Los recursos de Azure de esta sección comienzan a costar dinero inmediatamente, incluso si detiene el comando antes de que finalice.

Establecimiento del token JWT

  • Establezca el token JWT para el servidor MCP ejecutando el siguiente comando en el terminal en la parte inferior de la pantalla:

    # zsh/bash
    ./scripts/set-jwttoken.sh
    
    # PowerShell
    ./scripts/Set-JwtToken.ps1
    

Adición del token JWT a la configuración del entorno azd

  1. Agregue el token JWT a la configuración del entorno azd ejecutando el siguiente comando en el terminal en la parte inferior de la pantalla:

    # zsh/bash
    env_dir=".azure/$(azd env get-value AZURE_ENV_NAME)"
    mkdir -p "$env_dir"
    cat ./src/McpTodo.ServerApp/.env >> "$env_dir/.env"
    
    # PowerShell
    $dotenv = Get-Content ./src/McpTodo.ServerApp/.env
    $dotenv | Add-Content -Path ./.azure/$(azd env get-value AZURE_ENV_NAME)/.env -Encoding utf8 -Force
    

    Nota:

    De forma predeterminada, la aplicación cliente MCP está protegida por la característica de autenticación integrada de ACA. Puede desactivar esta característica antes de ejecutarse estableciendo azd up :

    azd env set USE_LOGIN false
    
  2. Ejecute el siguiente comando de la CLI para desarrolladores de Azure para el aprovisionamiento de recursos de Azure y la implementación de código fuente:

    azd up
    
  3. Use la tabla siguiente para responder a las indicaciones:

    Pronto Respuesta
    Nombre del entorno Use un nombre corto y en minúsculas. Agregue su nombre o alias. Por ejemplo: my-mcp-agent. El nombre del entorno se convierte en parte del nombre del grupo de recursos.
    Subscription Elija la suscripción en la que desea crear recursos.
    Ubicación (para hospedaje) Elija la ubicación de implementación del modelo de la lista.
    Cadena de conexión de OpenAI Pegue la cadena de conexión para el modelo de OpenAI que creó anteriormente en la sección Creación de la cadena de conexión del modelo de OpenAI .
  4. La implementación de la aplicación tarda entre 5 y 10 minutos.

  5. Una vez finalizada la implementación, puede acceder al agente de MCP mediante la dirección URL de la salida. La dirección URL tiene este aspecto:

    https://<env-name>.<container-id>.<region>.azurecontainerapps.io
    
  6. Abra la dirección URL en un explorador web para usar el agente de MCP.

Uso del agente MCP de TODO

Después de ejecutar el agente MCP, puede usar las herramientas que proporciona en modo de agente. Para usar herramientas de MCP en modo de agente:

  1. Vaya a la dirección URL de la aplicación cliente e inicie sesión en la aplicación.

    Nota:

    Si establece el USE_LOGIN valor falseen , es posible que no se le pida que inicie sesión.

  2. Escriba un mensaje como "Necesito enviar un correo electrónico a mi administrador el miércoles" en el cuadro de entrada de chat y observe cómo las herramientas se invocan automáticamente según sea necesario.

  3. El agente de MCP usa las herramientas proporcionadas por el servidor MCP para cumplir la solicitud y devolver una respuesta en la interfaz de chat.

  4. Experimente con otros mensajes como:

    Give me a list of to dos.
    Set "meeting at 1pm".
    Give me a list of to dos.
    Mark #1 as completed.
    Delete #1 from the to-do list.
    

Exploración del código

El repositorio de ejemplo contiene todos los archivos de código y configuración para la implementación de Azure del agente MCP. Las secciones siguientes le guiarán por los componentes clave del código del agente MCP.

Configuración y configuración del cliente MCP

La aplicación configura el cliente MCP en Program.cs. Esta configuración define cómo conectarse y qué opciones usar. El código usa varios patrones avanzados, incluidos los valores predeterminados de integración y servicio de .NET Aspire:

builder.Services.AddSingleton<IMcpClient>(sp =>
{
    var config = sp.GetRequiredService<IConfiguration>();
    var loggerFactory = sp.GetRequiredService<ILoggerFactory>();

    var uri = new Uri(config["McpServers:TodoList"]!);

    var clientTransportOptions = new SseClientTransportOptions()
    {
        Endpoint = new Uri($"{uri.AbsoluteUri.TrimEnd('/')}/mcp"),
        AdditionalHeaders = new Dictionary<string, string>
        {
            { "Authorization", $"Bearer {config["McpServers:JWT:Token"]!}" }
        }
    };
    var clientTransport = new SseClientTransport(clientTransportOptions, loggerFactory);

    var clientOptions = new McpClientOptions()
    {
        ClientInfo = new Implementation()
        {
            Name = "MCP Todo Client",
            Version = "1.0.0",
        }
    };

    return McpClientFactory.CreateAsync(clientTransport, clientOptions, loggerFactory).GetAwaiter().GetResult();
});

Detalles clave de implementación:

  • Configuración de transporte: SseClientTransportOptions admite eventos Server-Sent (SSE) y transporte HTTP que se puede transmitir. El método de transporte depende de la dirección URL del punto de conexión: los puntos de conexión que terminan con /sse el uso de eventos Server-Sent, mientras que los puntos de conexión terminan con /mcp HTTP que se puede transmitir. Este enfoque permite la comunicación en tiempo real entre el cliente y el servidor.
  • Encabezados de autenticación: los tokens JWT van en para AdditionalHeaders mantener la comunicación del servidor segura
  • Información de cliente: McpClientOptions indica al servidor el nombre y la versión del cliente.
  • Patrón de fábrica: McpClientFactory.CreateAsync() conecta y completa el protocolo de enlace de protocolo

Integración predeterminada del servicio .NET Aspire

La aplicación usa el patrón predeterminado de servicio de .NET Aspire para problemas transversales:

// McpTodo.ServiceDefaults/Extensions.cs
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
    builder.ConfigureOpenTelemetry();
    builder.AddDefaultHealthChecks();
    builder.Services.AddServiceDiscovery();
    
    builder.Services.ConfigureHttpClientDefaults(http =>
    {
        // Turn on resilience by default
        http.AddStandardResilienceHandler();
        // Turn on service discovery by default
        http.AddServiceDiscovery();
    });
    
    return builder;
}

Ventajas predeterminadas del servicio:

  • Métodos de extensión compuesta: el sistema usa un patrón de generador limpio para agregar características compartidas
  • Controladores de resistencia estándar: el sistema agrega reglas integradas de reintento, disyuntor y tiempo de espera.
  • Integración de detección de servicios: el sistema busca servicios automáticamente en entornos de contenedor.
  • OpenTelemetry de forma predeterminada: el sistema obtiene una supervisión completa sin ningún trabajo de configuración.

En el diagrama siguiente se muestra la relación entre los problemas transversales y los servicios de aplicación:

Diagrama que muestra la relación entre los problemas transversales y los servicios de aplicación.

Resolución de direcciones URL de configuración

El ejemplo incluye una resolución de direcciones URL sofisticada para distintos entornos:

// AspireUrlParserExtensions.cs
public static Uri Resolve(this Uri uri, IConfiguration config)
{
    var absoluteUrl = uri.ToString();
    if (absoluteUrl.StartsWith("https+http://"))
    {
        var appname = absoluteUrl.Substring("https+http://".Length).Split('/')[0];
        var https = config[$"services:{appname}:https:0"]!;
        var http = config[$"services:{appname}:http:0"]!;
        
        return string.IsNullOrWhiteSpace(https) ? new Uri(http) : new Uri(https);
    }
    // Handle other URL formats...
}

Características de administración de configuración:

  • Abstracción de detección de servicios: el sistema controla las direcciones URL de desarrollo y producción de forma limpia
  • Negociación de protocolo: el sistema elige PRIMERO HTTPS y, a continuación, vuelve a HTTP.
  • Convención de configuración: el sistema usa patrones estándar de configuración del servicio Aspire de .NET

Implementación de autenticación

En este ejemplo se usa la autenticación JWT (JSON Web Token) para proteger la conexión entre el cliente MCP y el servidor.

dotnet user-secrets --project ./src/McpTodo.ClientApp set McpServers:JWT:Token "$TOKEN"

Nota:

Los scripts crearon automáticamente la $TOKEN variable cuando ejecutó el script de Bash (set-jwttoken.sh) o PowerShell (Set-JwtToken.ps1) anteriormente en la sección Implementación en Azure . Estos scripts realizan los pasos siguientes:

  1. Ejecutar npm run generate-token en la aplicación de servidor MCP para crear un token JWT
  2. Análisis del archivo generado .env para extraer el valor de JWT_TOKEN
  3. Almacénelo automáticamente en secretos de usuario de .NET para MCPClient

El cliente MCP recupera el token JWT de la configuración e lo incluye en los encabezados HTTP para la autenticación al conectarse al servidor MCP:

AdditionalHeaders = new Dictionary<string, string>
{
    { "Authorization", $"Bearer {config["McpServers:JWT:Token"]!}" }
}

Este enfoque garantiza:

  • Comunicación segura: el sistema solo permite a los clientes con tokens válidos conectarse al servidor MCP.
  • Token-Based autorización: los tokens JWT permiten al sistema comprobar los usuarios sin almacenar datos de sesión
  • Administración de configuración: el sistema almacena tokens confidenciales de forma segura en secretos de usuario durante el desarrollo.

Integración de la autenticación de Azure Container Apps

La infraestructura muestra patrones de autenticación avanzados mediante características integradas de autenticación y autorización de Azure Container Apps ("Autenticación sencilla"):

// containerapps-authconfigs.bicep
resource containerappAuthConfig 'Microsoft.App/containerApps/authConfigs@2024-10-02-preview' = {
  properties: {
    identityProviders: {
      azureActiveDirectory: {
        enabled: true
        registration: {
          clientId: clientId
          openIdIssuer: openIdIssuer
        }
      }
    }
    login: {
      tokenStore: {
        enabled: true
        azureBlobStorage: {
          blobContainerUri: '${storageAccount.properties.primaryEndpoints.blob}/token-store'
          managedIdentityResourceId: userAssignedIdentity.id
        }
      }
    }
  }
}

Características avanzadas de autenticación:

  • autenticación deZero-Code: Azure Container Apps proporciona autenticación integrada
  • Identidad administrada para Storage: el sistema almacena tokens de forma segura sin cadenas de conexión.
  • Credenciales de identidad federada: el sistema habilita la identidad de carga de trabajo para la autenticación de estilo kubernetes.

En el diagrama siguiente se muestra el protocolo de enlace de seguridad entre componentes:

Diagrama que muestra el protocolo de enlace de seguridad entre componentes.

Detección y registro de herramientas

El cliente MCP detecta las herramientas disponibles del servidor durante la inicialización de componentes en Chat.razor:

protected override async Task OnInitializedAsync()
{
    messages.Add(new(ChatRole.System, SystemPrompt));
    tools = await McpClient.ListToolsAsync();
    chatOptions.Tools = [.. tools];
}

Funcionamiento de la detección de herramientas:

  1. Consulta de servidor: McpClient.ListToolsAsync() envía una solicitud al servidor MCP para enumerar las herramientas disponibles.
  2. Recuperación de esquemas: el servidor envía definiciones de herramientas con nombres, descripciones y esquemas de entrada
  3. Registro de herramientas: el sistema registra herramientas con el ChatOptions objeto , lo que los hace disponibles para el cliente de OpenAI.
  4. Seguridad de tipos: la McpClientTool clase hereda de AIFunction, lo que proporciona una integración fluida con Microsoft.Extensions.AI

En el diagrama siguiente se muestra cómo se analizan y registran los esquemas de herramientas:

Diagrama que muestra el flujo de registro y detección de herramientas.

Integración y invocación de funciones de OpenAI

La configuración del cliente de chat muestra cómo se integran las herramientas de MCP con Azure OpenAI:

var chatClient = openAIClient.GetChatClient(config["OpenAI:DeploymentName"]).AsIChatClient();

builder.Services.AddChatClient(chatClient)
                .UseFunctionInvocation()
                .UseLogging();

Ventajas de integración:

  • Llamada automática a funciones: la .UseFunctionInvocation() extensión activa la ejecución automática de herramientas en función de las decisiones de LLM.
  • Acceso sencillo a herramientas: las herramientas de MCP funcionan como funciones integradas para el modelo de OpenAI
  • Procesamiento de respuestas: el sistema agrega automáticamente resultados de herramientas al flujo de conversación.

implementación de chat de Real-Time

La interfaz de chat de Chat.razor muestra las respuestas de streaming y la ejecución de herramientas con patrones de Blazor avanzados:

private async Task AddUserMessageAsync(ChatMessage userMessage)
{
    CancelAnyCurrentResponse();

    // Add the user message to the conversation
    messages.Add(userMessage);
    chatSuggestions?.Clear();
    await chatInput!.FocusAsync();

    // Stream and display a new response from the IChatClient
    var responseText = new TextContent("");
    currentResponseMessage = new ChatMessage(ChatRole.Assistant, [responseText]);
    currentResponseCancellation = new();
    await foreach (var update in ChatClient.GetStreamingResponseAsync([.. messages], chatOptions, currentResponseCancellation.Token))
    {
        messages.AddMessages(update, filter: c => c is not TextContent);
        responseText.Text += update.Text;
        ChatMessageItem.NotifyChanged(currentResponseMessage);
    }

    // Store the final response in the conversation, and begin getting suggestions
    messages.Add(currentResponseMessage!);
    currentResponseMessage = null;
    chatSuggestions?.Update(messages);
}

Características de implementación de streaming:

  • Real-Time actualizaciones: GetStreamingResponseAsync() envía actualizaciones de respuesta bit a bit
  • Ejecución de herramientas: el sistema procesa las llamadas de función automáticamente durante el streaming.
  • Capacidad de respuesta de la interfaz de usuario: ChatMessageItem.NotifyChanged() actualiza la interfaz de usuario en tiempo real.
  • Compatibilidad con cancelación: los usuarios pueden cancelar operaciones de larga duración

Patrones avanzados de interfaz de usuario de Blazor

La implementación usa patrones avanzados de interfaz de usuario para actualizaciones en tiempo real:

Memory-Safe control de eventos:

// ChatMessageItem.razor
private static readonly ConditionalWeakTable<ChatMessage, ChatMessageItem> SubscribersLookup = new();

public static void NotifyChanged(ChatMessage source)
{
    if (SubscribersLookup.TryGetValue(source, out var subscriber))
    {
        subscriber.StateHasChanged();
    }
}

Integración de componentes web personalizados:

// ChatMessageList.razor.js
window.customElements.define('chat-messages', class ChatMessages extends HTMLElement {
    connectedCallback() {
        this._observer = new MutationObserver(mutations => this._scheduleAutoScroll(mutations));
        this._observer.observe(this, { childList: true, attributes: true });
    }
    
    _scheduleAutoScroll(mutations) {
        // Debounce the calls and handle smart auto-scrolling
        cancelAnimationFrame(this._nextAutoScroll);
        this._nextAutoScroll = requestAnimationFrame(() => {
            const addedUserMessage = mutations.some(m => 
                Array.from(m.addedNodes).some(n => 
                    n.parentElement === this && n.classList?.contains('user-message')));
            // Smart scrolling logic...
        });
    }
});

Administración avanzada del estado:

// Chat.razor
private void CancelAnyCurrentResponse()
{
    // If a response was cancelled while streaming, include it in the conversation so it's not lost
    if (currentResponseMessage is not null)
    {
        messages.Add(currentResponseMessage);
    }
    
    currentResponseCancellation?.Cancel();
    currentResponseMessage = null;
}

Ventajas de la interfaz de usuario de Blazor:

  • Componentes web híbridos: el sistema combina Blazor Server con elementos personalizados para mejorar el rendimiento.
  • Memory-Safe control de eventos: el sistema usa ConditionalWeakTable para evitar pérdidas de memoria.
  • Desplazamiento automático inteligente: el sistema proporciona un comportamiento de chat fácil de usar con desbouncing
  • Cancelación correcta: el sistema guarda trabajo parcial cuando los usuarios cancelan las operaciones

Flujo de solicitud/respuesta

A continuación se muestra cómo fluye una interacción típica del usuario a través del sistema:

  1. Entrada de usuario: el usuario escribe un mensaje como "Agregar "Comprar comestibles" a mi lista de tareas pendientes"
  2. Procesamiento de mensajes: el sistema agrega el mensaje al historial de conversaciones.
  3. Análisis de LLM: Azure OpenAI analiza la solicitud y decide qué herramientas usar
  4. Detección de herramientas: el modelo busca la herramienta MCP correcta (por ejemplo, addTodo)
  5. Ejecución de herramientas: el cliente MCP llama al servidor con los parámetros necesarios
  6. Procesamiento de respuesta: el sistema agrega la respuesta del servidor a la conversación.
  7. Actualización de la interfaz de usuario: el sistema muestra el resultado al usuario en tiempo real.

En el diagrama siguiente se muestra cómo fluyen los mensajes desde la entrada del usuario a través de OpenAI a la ejecución de herramientas y de vuelta a la interfaz de usuario:

Diagrama que muestra el flujo de solicitud/respuesta.

Administración de patrones asincrónicos

La aplicación muestra patrones asincrónicos sofisticados para las operaciones en segundo plano:

// ChatSuggestions.razor
public void Update(IReadOnlyList<ChatMessage> messages)
{
    // Runs in the background and handles its own cancellation/errors
    _ = UpdateSuggestionsAsync(messages);
}

private async Task UpdateSuggestionsAsync(IReadOnlyList<ChatMessage> messages)
{
    cancellation?.Cancel();
    cancellation = new CancellationTokenSource();
    
    try
    {
        var response = await ChatClient.GetResponseAsync<string[]>(
            [.. ReduceMessages(messages), new(ChatRole.User, Prompt)],
            cancellationToken: cancellation.Token);
        // Handle response...
    }
    catch (Exception ex) when (ex is not OperationCanceledException)
    {
        await DispatchExceptionAsync(ex);
    }
}

Ventajas de tareas en segundo plano:

  • Fire-and-Forget with Safety: el sistema usa _ = el patrón con el control de excepciones adecuado
  • Reducción de contexto inteligente: el sistema limita el historial de conversaciones para evitar el desbordamiento de tokens.
  • Cancelación inteligente: el sistema limpia correctamente las operaciones de competencia.

Control de errores y resistencia

La implementación incluye varios patrones de resistencia:

private void CancelAnyCurrentResponse()
{
    // If a response was cancelled while streaming, include it in the conversation so it's not lost
    if (currentResponseMessage is not null)
    {
        messages.Add(currentResponseMessage);
    }

    currentResponseCancellation?.Cancel();
    currentResponseMessage = null;
}

Características de resistencia:

  • Cancelación correcta: el sistema guarda respuestas en curso cuando los usuarios los cancelan.
  • Recuperación de conexiones: el transporte SSE controla automáticamente las caídas de conexión.
  • Administración de estado: el estado de la interfaz de usuario permanece coherente durante los errores.
  • Integración del registro: el sistema proporciona un registro completo para la depuración y la supervisión.

Comprobaciones de observabilidad y estado

La aplicación incluye patrones sofisticados de observabilidad:

Configuración de Smart Health Check:

// Extensions.cs
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
    if (app.Environment.IsDevelopment())
    {
        // All health checks must pass for app to be considered ready
        app.MapHealthChecks(HealthEndpointPath);
        
        // Only health checks tagged with "live" must pass for app to be considered alive
        app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
        {
            Predicate = r => r.Tags.Contains("live")
        });
    }
    return app;
}

OpenTelemetry con filtrado inteligente:

// Extensions.cs
.AddAspNetCoreInstrumentation(tracing =>
    // Exclude health check requests from tracing
    tracing.Filter = context =>
        !context.Request.Path.StartsWithSegments(HealthEndpointPath)
        && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)

Ventajas de observabilidad:

  • Environment-Aware puntos de conexión: exposición de la comprobación de estado consciente de la seguridad
  • Experiencia frente a preparación: patrones de comprobación de estado de estilo kubernetes
  • Reducción de ruido de telemetría: filtrado de comprobaciones de estado rutinarias de seguimientos

Configuración y configuración del entorno

La aplicación admite varios entornos mediante la configuración:

var openAIClient = Constants.GitHubModelEndpoints.Contains(endpoint.TrimEnd('/'))
                   ? new OpenAIClient(credential, openAIOptions)
                   : new AzureOpenAIClient(new Uri(endpoint), credential);

Opciones de configuración:

  • Azure OpenAI: las implementaciones de producción suelen usar el servicio Azure OpenAI.
  • Modelos de GitHub: los escenarios de desarrollo pueden usar modelos de GitHub
  • Desarrollo local: compatibilidad con instancias de servidor MCP locales
  • Implementación de contenedores: Azure Container Apps para el hospedaje de producción

Limpieza de recursos

Después de terminar de usar el agente MCP, limpie los recursos que creó para evitar incurrir en costos innecesarios.

Para limpiar los recursos, siga estos pasos:

  • Elimine los recursos de Azure creados por la CLI para desarrolladores de Azure mediante la ejecución del siguiente comando en el terminal en la parte inferior de la pantalla:

    azd down --purge --force
    

Limpieza de GitHub Codespaces

Elimine el entorno de GitHub Codespaces para maximizar las horas gratuitas por núcleo.

Importante

Para más información sobre el almacenamiento gratuito y las horas principales de la cuenta de GitHub, consulte Horas de almacenamiento y núcleo mensuales incluidas en GitHub Codespaces.

  1. Inicie sesión en el panel de GitHub Codespaces.

  2. Busque los espacios de código activos creados a partir del Azure-Samples/openai-mcp-agent-dotnet repositorio de GitHub.

  3. Abra el menú contextual del espacio de código y seleccione Eliminar.

Obtención de ayuda

Registre el problema en los problemas del repositorio.