From dd09623cc2bbba03a2eb3ce48bce10040d218e1c Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 16:12:59 +0100 Subject: [PATCH 1/6] .NET: Add Hosted-ToolboxMcpSkills sample Adds a hosted Foundry Responses sample that discovers MCP-based skills from a Foundry Toolbox and makes them available to the agent via AgentSkillsProvider. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/agent-framework-dotnet.slnx | 3 + .../Hosted-ToolboxMcpSkills/.env.example | 6 + .../Hosted-ToolboxMcpSkills/Dockerfile | 26 ++++ .../Dockerfile.contributor | 18 +++ .../HostedToolboxMcpSkills.csproj | 36 ++++++ .../Hosted-ToolboxMcpSkills/Program.cs | 114 ++++++++++++++++++ .../Hosted-ToolboxMcpSkills/README.md | 103 ++++++++++++++++ .../agent.manifest.yaml | 42 +++++++ .../Hosted-ToolboxMcpSkills/agent.yaml | 14 +++ 9 files changed, 362 insertions(+) create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/.env.example create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile.contributor create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/HostedToolboxMcpSkills.csproj create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml create mode 100644 dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.yaml diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index c6480cf02a..966d2370da 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -344,6 +344,9 @@ + + + diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/.env.example b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/.env.example new file mode 100644 index 0000000000..5c312b3f8e --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/.env.example @@ -0,0 +1,6 @@ +AZURE_AI_PROJECT_ENDPOINT= +ASPNETCORE_URLS=http://+:8088 +ASPNETCORE_ENVIRONMENT=Development +AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-5 +FOUNDRY_TOOLBOX_NAME= +AZURE_BEARER_TOKEN=DefaultAzureCredential diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile new file mode 100644 index 0000000000..d04bf72711 --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile @@ -0,0 +1,26 @@ +# Dockerfile for end-users consuming the Agent Framework via NuGet packages. +# +# This Dockerfile performs a full `dotnet restore` and `dotnet publish` inside the container, +# which only succeeds when the project references its dependencies via PackageReference (see the +# commented-out section in HostedToolboxMcpSkills.csproj). Contributors building from the +# agent-framework repository source must use Dockerfile.contributor instead because +# ProjectReference dependencies live outside this folder and cannot be restored from inside +# this build context. +# +# Use the official .NET 10.0 ASP.NET runtime as a parent image +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore +RUN dotnet publish -c Release -o /app/publish + +# Final stage +FROM base AS final +WORKDIR /app +COPY --from=build /app/publish . +EXPOSE 8088 +ENV ASPNETCORE_URLS=http://+:8088 +ENTRYPOINT ["dotnet", "HostedToolboxMcpSkills.dll"] diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile.contributor b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile.contributor new file mode 100644 index 0000000000..a01cc1e38c --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile.contributor @@ -0,0 +1,18 @@ +# Dockerfile for contributors building from the agent-framework repository source. +# +# This project uses ProjectReference to the local source, which means a standard +# multi-stage Docker build cannot resolve dependencies outside this folder. +# Pre-publish the app targeting the container runtime and copy the output: +# +# dotnet publish -c Debug -f net10.0 -r linux-musl-x64 --self-contained false -o out +# docker build -f Dockerfile.contributor -t hosted-toolbox-mcp-skills . +# docker run --rm -p 8088:8088 -e AGENT_NAME=hosted-toolbox-mcp-skills -e AZURE_BEARER_TOKEN=$AZURE_BEARER_TOKEN --env-file .env hosted-toolbox-mcp-skills +# +# For end-users consuming the NuGet package (not ProjectReference), use the standard +# Dockerfile which performs a full dotnet restore + publish inside the container. +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app +COPY out/ . +EXPOSE 8088 +ENV ASPNETCORE_URLS=http://+:8088 +ENTRYPOINT ["dotnet", "HostedToolboxMcpSkills.dll"] diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/HostedToolboxMcpSkills.csproj b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/HostedToolboxMcpSkills.csproj new file mode 100644 index 0000000000..d4c4155baf --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/HostedToolboxMcpSkills.csproj @@ -0,0 +1,36 @@ + + + + net10.0 + enable + enable + false + HostedToolboxMcpSkills + HostedToolboxMcpSkills + $(NoWarn); + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs new file mode 100644 index 0000000000..e6f39a38b1 --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Hosted Toolbox MCP Skills Agent +// +// Demonstrates how to host an agent that discovers MCP-based skills from a +// Foundry Toolbox MCP endpoint and injects them as AIContextProviders using +// AgentSkillsProviderBuilder.UseMcpSkills(). +// +// Required environment variables: +// AZURE_AI_PROJECT_ENDPOINT - Azure AI Foundry project endpoint +// FOUNDRY_TOOLBOX_NAME - Name of the Foundry Toolbox to connect to +// AZURE_AI_MODEL_DEPLOYMENT_NAME - Model deployment name (default: gpt-4o) + +using System.Net.Http.Headers; +using Azure.AI.Projects; +using Azure.Core; +using Azure.Identity; +using DotNetEnv; +using Hosted_Shared_Contributor_Setup; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Foundry.Hosting; +using ModelContextProtocol.Client; + +// Load .env file if present (for local development) +Env.TraversePath().Load(); + +var projectEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); +var deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o"; +var toolboxName = Environment.GetEnvironmentVariable("FOUNDRY_TOOLBOX_NAME") + ?? throw new InvalidOperationException("FOUNDRY_TOOLBOX_NAME is not set."); + +// Build the Toolbox MCP URL from the project endpoint and toolbox name. +var toolboxMcpServerUrl = $"{projectEndpoint.TrimEnd('/')}/toolboxes/{toolboxName}/mcp?api-version=v1"; + +// Use a chained credential: try a temporary dev token first (for local Docker debugging), +// then fall back to DefaultAzureCredential (for local dev via dotnet run / managed identity in production). +TokenCredential credential = new ChainedTokenCredential( + new DevTemporaryTokenCredential(), + new DefaultAzureCredential()); + +// ── Connect to the Foundry Toolbox MCP endpoint ───────────────────────────── +// Create an HttpClient that attaches a fresh Foundry bearer token to every request. +using var httpClient = new HttpClient(new BearerTokenHandler(credential, "https://ai.azure.com/.default") +{ + InnerHandler = new HttpClientHandler(), +}); + +Console.WriteLine($"Connecting to Foundry Toolbox '{toolboxName}' MCP server..."); + +await using var mcpClient = await McpClient.CreateAsync( + new HttpClientTransport( + new HttpClientTransportOptions + { + Endpoint = new Uri(toolboxMcpServerUrl), + Name = toolboxName, + TransportMode = HttpTransportMode.StreamableHttp, + AdditionalHeaders = new Dictionary + { + ["Foundry-Features"] = "Toolboxes=V1Preview", + }, + }, + httpClient)); + +// ── Discover MCP-based skills ──────────────────────────────────────────────── +var skillsProvider = new AgentSkillsProviderBuilder() + .UseMcpSkills(mcpClient) + .Build(); + +Console.WriteLine("MCP skills discovered and ready."); + +// ── Create the agent ───────────────────────────────────────────────────────── +AIAgent agent = new AIProjectClient(new Uri(projectEndpoint), credential) + .AsAIAgent(new ChatClientAgentOptions + { + Name = Environment.GetEnvironmentVariable("AGENT_NAME") ?? "hosted-toolbox-mcp-skills", + Description = "Hosted agent with MCP skills discovered from a Foundry Toolbox", + ChatOptions = new() + { + ModelId = deployment, + Instructions = "You are a helpful assistant.", + }, + AIContextProviders = [skillsProvider], + }); + +// ── Build the host ─────────────────────────────────────────────────────────── +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddFoundryResponses(agent); +builder.Services.AddDevTemporaryLocalContributorSetup(); // Local Docker debugging only - must not be used in production. + +var app = builder.Build(); +app.MapFoundryResponses(); + +// Contributor-only: in Development, also map the per-agent OpenAI route shape that live Foundry uses +// so a local REPL client can target this server via AIProjectClient.AsAIAgent(Uri agentEndpoint). +// Do not use this in production. Hosted Foundry agents only support the agent-endpoint path. +app.MapDevTemporaryLocalAgentEndpoint(); + +app.Run(); + +// --------------------------------------------------------------------------- +// DelegatingHandler: attaches a fresh Foundry bearer token to every request +// --------------------------------------------------------------------------- +internal sealed class BearerTokenHandler(TokenCredential credential, string scope) : DelegatingHandler +{ + private readonly TokenRequestContext _tokenContext = new([scope]); + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + AccessToken token = await credential.GetTokenAsync(this._tokenContext, cancellationToken).ConfigureAwait(false); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); + return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); + } +} diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md new file mode 100644 index 0000000000..448dbe957a --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md @@ -0,0 +1,103 @@ +# Hosted-ToolboxMcpSkills + +A hosted agent that discovers **MCP-based skills from a Foundry Toolbox** and makes them available to the agent using `AgentSkillsProviderBuilder.UseMcpSkills(mcpClient)`. + +The `AgentSkillsProvider` is attached to the agent as a context provider and implements the [Agent Skills](https://agentskills.io/) progressive-disclosure pattern. When the agent is prompted, it discovers available skills in the Foundry Toolbox via the provider: + +1. **Advertise** - skill names and descriptions are injected into the system prompt so the agent knows what is available. +2. **Load** - when the agent decides a skill is relevant, it retrieves the full skill body with detailed instructions via the provider. +3. **Read resources** - if a skill includes supplementary content (reference documents, assets), the agent reads them on demand via the provider. + +This way the full skill body and resources are only loaded when the agent actually needs them, reducing token usage. + +## Prerequisites + +- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) +- An Azure AI Foundry project with a deployed model (e.g., `gpt-4o`) +- A Foundry Toolbox already configured with skills provisioned +- Azure CLI logged in (`az login`) + +## Configuration + +Copy the template and fill in your values: + +```bash +cp .env.example .env +``` + +Edit `.env` and set your Azure AI Foundry project endpoint and toolbox name: + +```env +AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +ASPNETCORE_URLS=http://+:8088 +ASPNETCORE_ENVIRONMENT=Development +AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o +FOUNDRY_TOOLBOX_NAME=my-toolbox +``` + +> **Note:** `.env` is gitignored. The `.env.example` template is checked in as a reference. + +## Running directly (contributors) + +This project uses `ProjectReference` to build against the local Agent Framework source. + +```bash +cd dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills +dotnet run +``` + +The agent will start on `http://localhost:8088`. + +### Test it + +Using the Azure Developer CLI: + +```bash +azd ai agent invoke --local "What skills do you have available?" +``` + +## Running with Docker + +Since this project uses `ProjectReference`, use `Dockerfile.contributor` which takes a pre-published output. + +### 1. Publish for the container runtime (Linux Alpine) + +```bash +dotnet publish -c Debug -f net10.0 -r linux-musl-x64 --self-contained false -o out +``` + +### 2. Build the Docker image + +```bash +docker build -f Dockerfile.contributor -t hosted-toolbox-mcp-skills . +``` + +### 3. Run the container + +Generate a bearer token on your host and pass it to the container: + +```bash +# Generate token (expires in ~1 hour) +export AZURE_BEARER_TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv) + +# Run with token +docker run --rm -p 8088:8088 \ + -e AGENT_NAME=hosted-toolbox-mcp-skills \ + -e AZURE_BEARER_TOKEN=$AZURE_BEARER_TOKEN \ + --env-file .env \ + hosted-toolbox-mcp-skills +``` + +> **Note:** `AGENT_NAME` is passed via `-e` to simulate the platform injection. `AZURE_BEARER_TOKEN` provides Azure credentials to the container (tokens expire after ~1 hour). The `.env` file provides the remaining configuration. + +### 4. Test it + +Using the Azure Developer CLI: + +```bash +azd ai agent invoke --local "What skills do you have available?" +``` + +## NuGet package users + +If you are consuming the Agent Framework as a NuGet package (not building from source), use the standard `Dockerfile` instead of `Dockerfile.contributor`. See the commented section in `HostedToolboxMcpSkills.csproj` for the `PackageReference` alternative. diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml new file mode 100644 index 0000000000..8220b0e385 --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/AgentManifest.yaml +name: hosted-toolbox-mcp-skills +displayName: "Hosted Toolbox MCP Skills Agent" + +description: > + A hosted agent that discovers MCP-based skills from a Foundry Toolbox + and makes them available to the agent via the agent skills provider. + +metadata: + tags: + - AI Agent Hosting + - Azure AI AgentServer + - Responses Protocol + - Agent Framework + - MCP + - Model Context Protocol + - Agent Skills + - Foundry Toolbox + +template: + name: hosted-toolbox-mcp-skills + kind: hosted + protocols: + - protocol: responses + version: 1.0.0 + resources: + cpu: "0.25" + memory: 0.5Gi + environment_variables: + - name: AZURE_AI_MODEL_DEPLOYMENT_NAME + value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}" + - name: FOUNDRY_TOOLBOX_NAME + value: "{{FOUNDRY_TOOLBOX_NAME}}" +parameters: + properties: + - name: FOUNDRY_TOOLBOX_NAME + secret: false + description: Name of the Foundry Toolbox to connect to for MCP skill discovery +resources: + - kind: model + id: gpt-5 + name: AZURE_AI_MODEL_DEPLOYMENT_NAME diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.yaml b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.yaml new file mode 100644 index 0000000000..5f53abb2e2 --- /dev/null +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.yaml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml +kind: hosted +name: hosted-toolbox-mcp-skills +protocols: + - protocol: responses + version: 1.0.0 +resources: + cpu: "0.25" + memory: 0.5Gi +environment_variables: + - name: AZURE_AI_MODEL_DEPLOYMENT_NAME + value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME} + - name: FOUNDRY_TOOLBOX_NAME + value: ${FOUNDRY_TOOLBOX_NAME} From 4fa19c3eee5c1d2dc8a4c45353e97727f8602400 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 16:24:50 +0100 Subject: [PATCH 2/6] Align README and Program.cs default model to gpt-5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../responses/Hosted-ToolboxMcpSkills/Program.cs | 4 ++-- .../responses/Hosted-ToolboxMcpSkills/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs index e6f39a38b1..e3d94a4f67 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs @@ -9,7 +9,7 @@ // Required environment variables: // AZURE_AI_PROJECT_ENDPOINT - Azure AI Foundry project endpoint // FOUNDRY_TOOLBOX_NAME - Name of the Foundry Toolbox to connect to -// AZURE_AI_MODEL_DEPLOYMENT_NAME - Model deployment name (default: gpt-4o) +// AZURE_AI_MODEL_DEPLOYMENT_NAME - Model deployment name (default: gpt-5) using System.Net.Http.Headers; using Azure.AI.Projects; @@ -26,7 +26,7 @@ var projectEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); -var deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o"; +var deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5"; var toolboxName = Environment.GetEnvironmentVariable("FOUNDRY_TOOLBOX_NAME") ?? throw new InvalidOperationException("FOUNDRY_TOOLBOX_NAME is not set."); diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md index 448dbe957a..0c6b5ba60e 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/README.md @@ -13,7 +13,7 @@ This way the full skill body and resources are only loaded when the agent actual ## Prerequisites - [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) -- An Azure AI Foundry project with a deployed model (e.g., `gpt-4o`) +- An Azure AI Foundry project with a deployed model (e.g., `gpt-5`) - A Foundry Toolbox already configured with skills provisioned - Azure CLI logged in (`az login`) @@ -31,7 +31,7 @@ Edit `.env` and set your Azure AI Foundry project endpoint and toolbox name: AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ ASPNETCORE_URLS=http://+:8088 ASPNETCORE_ENVIRONMENT=Development -AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o +AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-5 FOUNDRY_TOOLBOX_NAME=my-toolbox ``` From 0b3792deca1acb73074d6b3313e66623ff43b27d Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 16:25:34 +0100 Subject: [PATCH 3/6] Clarify MCP skills provider log to avoid implying eager discovery Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../responses/Hosted-ToolboxMcpSkills/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs index e3d94a4f67..493529f363 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs @@ -62,12 +62,12 @@ }, httpClient)); -// ── Discover MCP-based skills ──────────────────────────────────────────────── +// ── Configure MCP-based skills provider ────────────────────────────────────── var skillsProvider = new AgentSkillsProviderBuilder() .UseMcpSkills(mcpClient) .Build(); -Console.WriteLine("MCP skills discovered and ready."); +Console.WriteLine("MCP skills provider configured."); // ── Create the agent ───────────────────────────────────────────────────────── AIAgent agent = new AIProjectClient(new Uri(projectEndpoint), credential) From c906f237ca607fd3bb9b36853a05a0d8341e4ff8 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 16:52:52 +0100 Subject: [PATCH 4/6] Drop redundant skills provider configured log Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../responses/Hosted-ToolboxMcpSkills/Program.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs index 493529f363..e8090e89a9 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs @@ -67,8 +67,6 @@ .UseMcpSkills(mcpClient) .Build(); -Console.WriteLine("MCP skills provider configured."); - // ── Create the agent ───────────────────────────────────────────────────────── AIAgent agent = new AIProjectClient(new Uri(projectEndpoint), credential) .AsAIAgent(new ChatClientAgentOptions From a9a3444117950a0d51eaae538349909685c3a313 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 17:18:35 +0100 Subject: [PATCH 5/6] Add Foundry Toolbox Skills tag to manifest Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml index 8220b0e385..2887336252 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.yaml @@ -16,6 +16,7 @@ metadata: - Model Context Protocol - Agent Skills - Foundry Toolbox + - Foundry Toolbox Skills template: name: hosted-toolbox-mcp-skills From 651de9e59d018d3ac8d33a11c8b718200a374a01 Mon Sep 17 00:00:00 2001 From: SergeyMenshykh Date: Fri, 29 May 2026 17:42:26 +0100 Subject: [PATCH 6/6] Simplify BearerTokenHandler by deriving from HttpClientHandler Removes the need for an explicit InnerHandler. Enables CheckCertificateRevocationList to satisfy CA5399. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../responses/Hosted-ToolboxMcpSkills/Program.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs index e8090e89a9..f8ca3f4991 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Program.cs @@ -41,10 +41,7 @@ // ── Connect to the Foundry Toolbox MCP endpoint ───────────────────────────── // Create an HttpClient that attaches a fresh Foundry bearer token to every request. -using var httpClient = new HttpClient(new BearerTokenHandler(credential, "https://ai.azure.com/.default") -{ - InnerHandler = new HttpClientHandler(), -}); +using var httpClient = new HttpClient(new BearerTokenHandler(credential, "https://ai.azure.com/.default") { CheckCertificateRevocationList = true }); Console.WriteLine($"Connecting to Foundry Toolbox '{toolboxName}' MCP server..."); @@ -97,9 +94,9 @@ app.Run(); // --------------------------------------------------------------------------- -// DelegatingHandler: attaches a fresh Foundry bearer token to every request +// HttpClientHandler: attaches a fresh Foundry bearer token to every request // --------------------------------------------------------------------------- -internal sealed class BearerTokenHandler(TokenCredential credential, string scope) : DelegatingHandler +internal sealed class BearerTokenHandler(TokenCredential credential, string scope) : HttpClientHandler { private readonly TokenRequestContext _tokenContext = new([scope]);