Add Foundry Toolbox resource and deploy pipeline - #17742
Conversation
Adds first-class Microsoft Foundry Toolbox support to Aspire.Hosting.Foundry. Toolboxes are a Foundry data-plane construct (no ARM/Bicep) that bundle tools for agents. Aspire now models them as a resource that is created via the AgentToolboxes data plane API at deploy time, after the parent project's endpoint becomes ready. Public API: - FoundryToolboxResource (parented to AzureCognitiveServicesProjectResource, implements IResourceWithConnectionString) - AddToolbox extension on the project resource builder - WithWebSearchTool, WithMcpTool, WithAISearchTool tool-definition extensions Deploy is wired as a PipelineStepAnnotation so it runs alongside Azure ARM provisioning: a publish-mode deploy step and a run-mode before-start step that both call AgentToolboxes.CreateToolboxVersionAsync once the project endpoint is reachable. Retries with Polly handle the brief window where the freshly provisioned project endpoint is still warming up. Polyglot (TypeScript): AddToolboxForPolyglot and WithMcpToolForPolyglot use AspireExport/AspireUnion so the TS apphost can call addToolbox, withMcpTool, withWebSearchTool, and withAISearchTool with TS-friendly union types. Validated end-to-end against a real Azure AI Foundry account: the deploy hook fired in 3.4s after the project reached Running, and the toolbox was confirmed present on the data plane (toolboxes API returned field-tools, default_version 1). 102/102 tests pass in Aspire.Hosting.Foundry.Tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17742Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17742" |
Temporary instrumentation in AsHostedAgent_ResolvesToolboxConnectionString to capture python app + hosted agent + project env vars and annotations into the assertion failure message. To be reverted once the CI vs local divergence is identified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ion test AsHostedAgent_ResolvesToolboxConnectionString was failing on CI (Windows + Ubuntu) with `InvalidOperationException: No output for APPLICATION_INSIGHTS_CONNECTION_STRING on resource my-project`. AzureHostedAgentResource.GetResolvedEnvironmentVariablesAsync walks every env var callback on the target resource. On CI the python app picks up extra WithReference(project)-style callbacks that splat AzureCognitiveServicesProjectResource.GetConnectionProperties() (Uri / ConnectionString / ApplicationInsightsConnectionString) as MY_PROJECT_* env vars. Those references resolve through BicepOutputReference, which throws if the named output is not seeded on the test resource. The test is only asserting on ConnectionStrings__field-tools, so unrelated extra env vars should not break it. Seed APPLICATION_INSIGHTS_CONNECTION_STRING (in addition to the existing endpoint output) so every project output reachable through GetConnectionProperties() can be resolved. Also drops the temporary diagnostic dump that was wrapped around the assertion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two follow-ups to the Foundry Toolbox MCP integration: 1. FoundryToolboxMcpToolDefinition now exposes AuthorizationTokenExpression and a case-insensitive Headers dictionary. ToProjectsAgentToolAsync resolves both at deploy time and forwards them to ResponseTool.CreateMcpTool so private MCP servers behind a bearer token or custom headers can be wired up declaratively. The new WithMcpTool(..., configure) overloads thread an optional configuration callback so callers don't have to grab the resource to mutate the tool definition. 2. FoundryToolboxResource now installs a PipelineConfigurationAnnotation that walks each MCP tool's EndpointExpression via IValueWithReferences and wires the toolbox deploy-compute step to depend on the deploy-compute step of every referenced compute resource that lives in the app model. This removes the manual WaitFor(...) ordering caveat for the common case where an MCP tool points at a sibling project/container/app service. Run-mode waits are filtered to resources that implement both IComputeResource and IResourceWithWaitSupport so we don't hang on Azure-only or model-only resources that never publish a Running state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
Adds an end-to-end playground showcasing the new polyglot auth/headers support on FoundryToolboxMcpToolOptions: * WithMcpToolForPolyglot now accepts an optional FoundryToolboxMcpToolOptions (AuthorizationToken, Headers), projected onto the existing .NET configure callback so polyglot AppHosts can wire bearer-token / custom-header MCP servers without dropping to C#. * playground/FoundryAgentToolboxTs/ - a TypeScript AppHost (apphost.mts) that wires a Foundry agent + Toolbox to a custom Node MCP server which validates Authorization: Bearer <token>. A secret mcp-bearer-token parameter is fed into both the MCP server (env var) and the toolbox tool definition (authorizationToken), with an extra x-app-source custom header to exercise the headers feature. * The MCP server uses @modelcontextprotocol/sdk with the streamable HTTP transport, exposes lookup_employee and record_note tools, and was smoke-tested end-to-end (init handshake, tools/list, tools/call) with bearer auth enforced. NuGet.config and 13.5.0-dev pins are temporary until this PR ships in a release of Aspire.Hosting.Foundry; the README documents the dev-loop workflow and the cleanup steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Polyglot auth/headers support + TypeScript playgroundThe latest commit adds end-to-end coverage for bearer-token / custom-header MCP servers from a polyglot AppHost, and a TS playground that exercises it. What changed
Validated locally
Caveats (worth being honest about)
How to try itFrom the repo root: dotnet pack src/Aspire.Hosting.Foundry/Aspire.Hosting.Foundry.csproj -c Debug --no-restore
dotnet pack src/Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.csproj -c Debug --no-restore
cd playground/FoundryAgentToolboxTs/mcp-server && npm install && cd ..
aspire restore --apphost apphost.mts
aspire publish --non-interactive # or: aspire start |
PR Testing ReportPR Information
CLI Version Verification
Changes AnalyzedFiles changed (highlights)
Change categories
Test Scenarios ExecutedS1 — CLI version pin matches PR headCoverage: Verification
S2 —
|
| # | Scenario | Coverage | Result | Exit |
|---|---|---|---|---|
| S1 | CLI version pin matches PR head | Verification | ✅ Pass | — |
| S2 | aspire-empty publish baseline |
Happy path | ✅ Pass (4/4) | 0 |
| S3 | TS Foundry Toolbox playground restore + publish | Happy path (PR target) | ✅ Pass (10/10) | 0 |
| S4 | --apphost <nonexistent> for restore + publish |
Unhappy path | ✅ Pass (clean error) | 7 |
| S5 | Non-interactive publish without secret param | Unhappy path | ✅ Pass (clean failure, exit 6) | 6 |
Overall Result
✅ PR VERIFIED
The new WithMcpTool(name, urlExpr, options) polyglot binding on Aspire.Hosting.Foundry works end-to-end from a TypeScript apphost through aspire restore and aspire publish against the PR's CLI build. The authorizationToken and headers options flow cleanly through the codegen layer; publish produces correct Foundry Bicep artifacts; unhappy paths fail loudly with consistent exit codes.
Recommendations / follow-ups
- Playground
packageSourceMappingpapercut.Aspire.Hosting.Foundrypulls a deep transitive Aspire surface (Aspire.Hosting.Azure.*,Aspire.Hosting.CodeGeneration.TypeScript, and notablyAspire.TypeSystemwhich lacks the.Hosting.prefix). When pinning a playground to a hive viaNuGet.configpackageSourceMapping, narrow patterns likeAspire.Hosting.Foundryor evenAspire.Hosting.*fail. Use<package pattern="Aspire.*" />to be safe. Worth a docs note next to the existing playground README, or a smallaspire-restore-time hint. - Sample apphost should optionally model a compute env. The TS playground's
mcp-serverNode app is defined but never makes it into the publish artifacts because there's noaddAzureContainerAppEnvironmenton the builder. Documenting (or wiring) a compute env in the sample would let a real user actually deploy the MCP alongside Foundry and exercise the bearer-token round-trip from the Foundry data plane. Today the sample proves the binding works; it doesn't prove an actually-reachable MCP gets called. - Missing parameter name in non-interactive error message. S5 surfaced
The option must be specified when running in non-interactive mode.with the parameter name blank. Likely a small formatter bug; consider a regression test on a hyphenated parameter name. - Run-mode caveat (already documented in PR/README, repeating for visibility). Foundry data-plane →
localhost:<port>is not reachable. Run-mode exercising of the agent against the MCP requires a tunnel (dev tunnels / ngrok). The PR is honest about this; publish-mode against ACA with public ingress is the supported E2E. Per author's PR comments, the deploy-time ordering between the toolboxmcp-toolregistration and the MCP compute container is also a known gap.
Evidence
All evidence files live under C:\Users\davifowl\AppData\Local\Temp\aspire-pr-test-7a335772\:
scenario-empty/empty-publish.log— S2 baseline publish outputscenario-foundry/restore3.log— S3 restore outputscenario-foundry/publish.log,publish2.log— S3 publish output (10/10 steps)scenario-foundry/FoundryPlay/aspire-output/{main,foundry/foundry,project/project}.bicep— generated artifactsscenario-unhappy-restore.log,scenario-unhappy-publish.log— S4 nonexistent-apphost outputscenario-clean/publish-noparam.log— S5 clean "missing required input" failure
Follow-up: in-repo dogfood test of
|
| Resource | Type | State |
|---|---|---|
mcp-server |
Executable (npm) | Running, Healthy, http://localhost:<port> |
mcp-server-installer |
Executable (npm install) | Finished, exit 0 |
foundry |
FoundryResource | Starting (needs Azure creds) |
project |
AzureCognitiveServicesProjectResource | Starting |
field-tools |
FoundryToolboxResource | Waiting for project |
foundry-roles |
AzureRoleAssignmentResource | Starting |
chat |
FoundryDeploymentResource | Starting |
Note for the earlier comment
My earlier dogfood report recommended that the docs call out a packageSourceMapping papercut for external testers building synthetic test fixtures. That recommendation does not apply to in-repo developers — the existing playground/FoundryAgentToolboxTs/NuGet.config already covers this case, and dotnet pack + aspire start/publish from the playground dir is the supported in-repo workflow. The papercut only matters if someone outside the repo tries to construct their own minimal test against the PR-built packages.
Result
✅ Verified end-to-end: pack → restore → publish (10/10 steps, bicep emitted) → start → dashboard healthy → MCP bearer auth round-trip with tools/call returning the expected payload.
Follow-up: two dogfood findings from a full Azure E2EI took the playground all the way through to a real Finding 1 — polyglot AppHostServer cross-ALC
|
| Piece | Value |
|---|---|
| Playground | playground/FoundryAgentToolboxTs (this branch) |
| Foundry account | foundry-a3lhnn2n4wpfk.services.ai.azure.com, project project |
| Toolbox | field-tools (toolbox_50aa9be1ce950b7c9bacebc7dd2d3c58a9e2c508), version 1 |
| MCP server | Node @modelcontextprotocol/sdk HTTP transport at https://mcp-server.blackforest-b4169b0d.eastus2.azurecontainerapps.io/mcp |
| Deploy CLI | aspire 13.4.0+64efcefb + this branch's Aspire.Hosting.Foundry in the NuGet cache |
… AppHost
The natural FoundryToolbox{WebSearch,Mcp}ToolDefinition.ToProjectsAgentToolAsync
implementation goes through ResponseTool.Create*().AsAgentTool(), which internally
calls ModelReaderWriter.Write<T> on an OpenAI.Responses tool. In a normal .NET
process this works. In the polyglot (TypeScript) AppHostServer, IntegrationLoadContext
loads probe assemblies into a separate ALC, and the prebuilt host's System.ClientModel
1.10.0 ends up bound to OpenAI in the default ALC while the integration's
System.ClientModel 1.11.0 lives in the probe ALC. The two SCMs surface as distinct
CLR assemblies, so the IPersistableModel<WebSearchTool> interface check inside
ModelReaderWriter.Write fails with a misleading 'must implement IEnumerable or
IPersistableModel<T>' exception.`Fix: stop calling MRW.Write across the ALC boundary. Both definitions now hand-build
the OpenAI Responses wire JSON and feed it to MRW.Read<ProjectsAgentTool>(...,
AzureAIProjectsAgentsContext.Default), which stays inside a single ALC (BCL +
Azure.AI.Projects.Agents + probe-ALC SCM). Wire shapes match openai-dotnet's
McpTool.Serialization.cs and WebSearchTool.Serialization.cs.`Also widens the polyglot WithMcpToolForPolyglot union to accept ReferenceExpression
so TS apphosts can use refExpr to compose URLs like \
efExpr\\/mcp\\.`Validated end-to-end against playground/FoundryAgentToolboxTs deployed to Azure:
aspire deploy completes deploy-field-tools cleanly and the resulting toolbox
version contains both {type:web_search} and the full MCP tool with auth + headers.`Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pology Iterates on playground/FoundryAgentToolboxTs to exercise the full bearer-auth MCP path against a real Foundry data plane:`- apphost.mts: dual run/publish topology. In run mode the local MCP server is fronted by an Aspire dev tunnel so the Foundry data plane can reach it; in publish mode it deploys as a NodeApp container with public ingress and the toolbox points at its public ACA endpoint. Documents the Foundry data-plane inline-auth gap inline. - mcp-server/src/server.ts: bearer auth middleware + request logging so we can verify whether the Foundry proxy is forwarding the Authorization header. - scripts/invoke-toolbox.mjs: standalone Node consumer that creates a Foundry agent against the deployed toolbox and runs a thread end-to-end. Useful for smoke-testing toolbox deploys without the dashboard. - NuGet.config / aspire.config.json: add Aspire.Hosting.DevTunnels and Aspire.Hosting.Azure.AppContainers package mappings.`Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
❓ CLI E2E Tests unknown — 110 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26728980717 |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add ownership-aware, idempotent Toolbox version reconciliation; remove unsupported inline MCP authentication; add unit, polyglot, and Azure deployment coverage; and remove the temporary authentication playground. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: 5
New issues introduced by this change (7)
| Severity | Finding |
|---|---|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs — AddConnection(search) generates a new connection-{Guid} physical name on every AppHost process… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReconciler.cs — This has a time-of-check/time-of-use race: two deploys can both observe no toolbox, then create… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxResource.cs — Waiting for a local compute resource to reach Running does not make its endpoint reachable from… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs — The public name supplied to WithWebSearchTool is not serialized into this wire payload; it only… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs — WithAISearchTool accepts a tool name, but this SDK object is created without assigning its… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs — This adds the primary public Toolbox entry point and new connection properties, but… |
|
tests/Aspire.Deployment.EndToEnd.Tests/FoundryHostedAgentDeploymentTests.cs — The deployment test exercises only Web Search, so it cannot catch the Azure AI Search path's… |
What changed in this PR
Adds first-class Microsoft Foundry Toolbox resources, tool definitions, connection properties, and deployment reconciliation.
Changes:
- Adds Toolbox builder APIs for Web Search, MCP, and Azure AI Search.
- Integrates Toolbox reconciliation into run and deployment pipelines.
- Adds unit, polyglot, deployment E2E, and playground coverage.
| File | Description |
|---|---|
FoundryToolboxBuilderExtensions.cs |
Adds Toolbox fluent APIs. |
FoundryToolboxOptions.cs |
Defines polyglot options. |
FoundryToolboxResource.cs |
Models lifecycle, connections, and pipeline steps. |
FoundryToolboxReconciler.cs |
Implements version reconciliation. |
FoundryToolboxToolDefinition.cs |
Converts supported tool definitions. |
ToolboxTests.cs |
Tests resources, tools, and pipelines. |
FoundryToolboxReconcilerTests.cs |
Tests reconciliation behavior. |
FoundryHostedAgentDeploymentTests.cs |
Adds Azure deployment coverage. |
TypeScript/apphost.mts |
Exercises generated Toolbox APIs. |
FoundryAgentBasic.AppHost/AppHost.cs |
Adds a playground example. |
Make search connections deterministic, serialize tool names, close the initial-version promotion race, reject local MCP endpoints, document Toolbox usage, and extend Azure Search deployment coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: 2
New issues introduced by this change (5)
| Severity | Finding |
|---|---|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs — indexName cannot be optional here: the Foundry Azure AI Search tool contract requires… |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxResource.cs — These sets model Aspire resource identities but use ordinal comparison. Resource names are… |
|
src/Aspire.Hosting.Foundry/README.md — The new Toolbox feature has no corresponding official Toolbox link in the README's Additional… |
|
tests/Aspire.Hosting.Foundry.Tests/ToolboxTests.cs — This assertion only proves that ModelReaderWriter returned an object; it does not verify the… |
|
tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts — This fixture omits the options argument, so the new [AspireDto] projection and the advertised… |
Issues resolved since last review (7)
| Severity | Finding |
|---|---|
tests/Aspire.Deployment.EndToEnd.Tests/FoundryHostedAgentDeploymentTests.cs — The deployment test exercises only Web Search, so it cannot catch the Azure AI Search path's… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs — This adds the primary public Toolbox entry point and new connection properties, but… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs — WithAISearchTool accepts a tool name, but this SDK object is created without assigning its… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs — The public name supplied to WithWebSearchTool is not serialized into this wire payload; it only… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxResource.cs — Waiting for a local compute resource to reach Running does not make its endpoint reachable from… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReconciler.cs — This has a time-of-check/time-of-use race: two deploys can both observe no toolbox, then create… View resolved comment |
|
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs — AddConnection(search) generates a new connection-{Guid} physical name on every AppHost process… View resolved comment |
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
playground/FoundryAgentBasic/FoundryAgentBasic.AppHost/AppHost.cs:11
- This comment says the toolbox is created only at deploy time, but this AppHost also reconciles it during
aspire runvia the background before-start path. Describe both modes so the playground does not contradict the resource lifecycle.
// Add a Foundry Toolbox with a single WebSearch tool. The toolbox is created on the Foundry data
// plane at deploy time via AgentToolboxes.CreateToolboxVersionAsync.
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxBuilderExtensions.cs:216
- This bypasses the existing Azure AI Search connection overload's role wiring (
ConnectionBuilderExtensions.cs:238-245). The Foundry project identity therefore receives neitherSearchIndexDataReadernorSearchServiceContributor, so the toolbox can be created but Azure AI Search tool calls will fail authorization. Apply the same role assignments before creating the deterministic connection.
var connection = projectBuilder.AddSearchConnection(connectionName, search.Resource);
Require Azure AI Search index names and role assignments, align resource-name comparison, cover MCP serialization and polyglot options, and complete Toolbox documentation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Mixed-tool readiness can report success without discovering any tools from configured MCP servers.
Review tier: Balanced
Findings: None
Suppressed comments (1)
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxResource.cs:433
- Mixed toolboxes can be marked
Runningbefore any configured MCP server is usable. This list drops everyFoundryToolboxMcpToolDefinition, so discovery of a built-in tool satisfies the probe even when an MCP server contributes zero tools. Foundry exposes MCP tools with a{serverLabel}.prefix; require at least one discovered tool for each configured server label (while retaining exact checks for built-ins), and cover the mixed-tool case.
var requiredToolNames = _tools
.Where(tool => tool is not FoundryToolboxMcpToolDefinition)
.Select(tool => tool.Name)
.ToArray();
Keep mixed Toolboxes in readiness until built-in tools are present and each configured MCP server label contributes at least one discovered tool. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Luis Quintanilla (luisquintanilla)
left a comment
There was a problem hiding this comment.
Thanks Tommaso Stocchi (@tommasodotNET). I re-reviewed the current head (7205ea9f) against the gaps I raised earlier. The lifecycle, approval-policy, reconciliation, RBAC, readiness, and MCP discovery changes address my concerns. Current CI is green, and I found no blocking regressions.
Approved from my side. Nice work closing this out.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Tests selector5 / 99 PR test projects · 3 PR jobs · 2 advisory-only targets, from 19 changed files. Selected PR test projects (5 / 99)
Selected PR jobs (3)
Advisory workflow impact (2)
How these were chosen — grouped by what changed🔧 📄 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🧪 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
Selection computed for commit |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Existing-mode readiness rejects valid skill-only Foundry Toolboxes.
Review tier: Balanced
Findings: None
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs:104
- Existing-mode readiness incorrectly requires
tools/listto return at least one tool when there are no modeled expectations. Foundry supports skill-only Toolboxes, where skills are exposed throughresources/list;AsExisting()therefore times out and marks a valid skill-only Toolbox as failed. When both expectation lists are empty, a successful MCP handshake should be sufficient, or the probe must also checkresources/list.
|
Pull request created: #1628
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1628 targeting Documented the new Foundry Toolbox resource added in this PR. Updated Note This draft PR needs human review before merging. |
|
🔍 CI Failure Analysis: Transient Infrastructure Failure The CI build failed due to transient infrastructure issues. Failed jobs:
If a rerun was not already requested automatically, visit the workflow run page to rerun the failed jobs manually. |
…ps (#1780) ## Summary <!-- Describe what this pull request changes and why. --> Reconcile the 13.6 wiki audit and **all 25 open `docs-from-code` proposals targeting `release/13.6`** against the actual release source. Add missing canonical guidance rather than putting all coverage in What's new. This is a new, isolated feature PR into `release/13.6`; it does not update the release rollup #1599, merge or close another proposal, or push directly to a release branch. **Draft with explicit remaining packaging/validation gates:** the six REPL walkthroughs are source-verified, but current publicly available 13.6 packages do not contain the late `WithRepl` exports. Generated API catalogs have deliberately not been fabricated or refreshed from 14.x. See the open checklist below. ### Evidence baseline - Documentation base: `717442f6666948bcf77f3d704dc2dadf7c080ec2`. - Product source of truth: [`microsoft/aspire@e8fd6fbb954f50ccd2e66479538392f65e13e71d`](https://github.com/microsoft/aspire/tree/e8fd6fbb954f50ccd2e66479538392f65e13e71d), current `release/13.6` at audit time. Source was read from that Git object, not the stale source working directory. - [13.6 wiki](https://github.com/microsoft/aspire/wiki/13.6-Change-log) snapshot `8e01a371d4f16a1306e48174d4cf1fdeca714348`, whose cutoff is product PR 20511. Later backports 20541/20546/20548 are included here. - Proposal base branches alone were **not** used as proof of release membership. Direct ancestry and known release backports were checked. Four fallback-targeted proposals are excluded below. - Wiki link corrections: its REPL link #1752 actually covers Sandboxes; the REPL proposal is #1740. Its AOT link #1714 covers PFX certificates, not AOT. ### Complete audit-gap checklist Checked items mean documentation coverage is implemented, not that cloud deployment or every product runtime scenario was executed. - [x] **1. Dotnet API graduation:** correct removal to **13.6**, not 14.0, in What's new, both Dotnet guides, and the diagnostic page; preserve the prerelease package caveat. This applies to core `AddDotnetProject`, `DotnetProjectResource`, and related `WithBuildEnvironment` overloads, not all uses of the diagnostic. Source: microsoft/aspire#20496. - [x] **2. Sandboxes:** remove obsolete API suppressions in the article and deployment guide while preserving Azure service preview/access and prerelease package limitations. Source: microsoft/aspire#20483. - [x] **3. Docked REPL documentation:** all six PostgreSQL/MySQL/MongoDB/SQL Server/Redis/Valkey guides plus the article now cover opt-in `WithRepl`/`withRepl`, run-only availability, actual client privileges, credential handling, and explicit exit versus closing a viewer. Source: microsoft/aspire#20419, backport of microsoft/aspire#20231. Package-backed checks remain open below. - [x] **4. Terminal CLI flag:** update current 13.6 article, `with-terminal`, and all three terminal command references. Preserve `terminals.v1` and experimental hosting API distinctions. Current configuration/schema data had no flag entry to remove; historical 13.5 notes remain historical. Source: microsoft/aspire#20548. - [x] **5. First-party Rust:** rewrite both canonical Rust guides around `Aspire.Hosting.Rust`; document Cargo versus application arguments, typed targets, debugging, generated Dockerfiles, workspace context, ABI constraints, and Toolkit migration. Bacon remains explicitly Toolkit-only. Add exact first-party package mapping. Source: microsoft/aspire#18906 and current Rust README. - [x] **6. Agent setup:** align command reference, skills guide, AI-agent guide, and article on MCP opt-in, `--mcp`, chained/non-interactive behavior, seven-skill catalog, Project v2 migration, and Copilot app detection. Also fix stale default-selection text: all applicable bundle skills are preselected; companion tools remain opt-in. Sources: microsoft/aspire#19893, microsoft/aspire#20405, microsoft/aspire#19820. - [x] **7. Deno AppHost runtime:** document Deno 2+ detection, commands, permissions, native watch/type checking, doctor, and `DENO_CERT`, separately from Deno guest hosting. Source: microsoft/aspire#18627, distinct from microsoft/aspire#18628. - [x] **8. Native AOT / Fluent UI v5:** concise article, dashboard exploration, and standalone guidance; automatic packaged-dashboard selection, no invented performance figures. Source: microsoft/aspire#19565 and release packaging sources. - [x] **9. NuGet:** document bundled in-process operations, credential providers, non-interactive authentication, and realistic troubleshooting. Correct the proposal's `dotnet nuget locals` authentication advice: cache commands do not authenticate a feed. Source: microsoft/aspire#20391. - [x] **10. Multithreaded builds:** article and coordinated-build guide explain `-mt`, SDK detection, distinct project/file-based SDK floors, and fallback. Source: microsoft/aspire#20441. - [x] **11. Radius:** add a real deployment guide with C#/TypeScript setup, recipe-backed connections versus local endpoints, per-resource credential behavior, unauthenticated Redis limitation, secret exposure boundaries, and actionable runtime diagnostics 070–091. Wire navigation and exact package mapping. Source: microsoft/aspire#19555 and release README. - [x] **12. Connection aliases:** replace contradictory no-encoding guidance, retain composed logical-key-first lookup and portable-target behavior, explain collision detection and custom-publisher metadata. Source: microsoft/aspire#19729. - [x] **13. Connector Namespace / Toolbox / provisioning:** add Connector Namespace walkthrough, security/consent/revocation limits and mapping/sidebar; add Foundry Toolbox walkthrough, connection properties, roles, index prerequisites, approval enforcement boundaries, immutable versions, and existing-resource behavior. Extend existing Azure provisioning guide without a duplicate page. Sources: microsoft/aspire#19024, microsoft/aspire#17742, microsoft/aspire#20131. - [x] **14. Remaining high-impact items:** article covers opt-in manifest-aware DNX and new-template CLI bundling (existing SDK guides retained), migration skill and Copilot app detection; canonical inline `CsiVolumeSourceV1`/`VolumeV1.Csi` example, management links, Cosmos vNext telemetry, and AI Inference `GetModelInfoAsync`/`/info` health checks with `DisableHealthChecks`. No Azure OpenAI health-check claim. Sources: microsoft/aspire#19310, microsoft/aspire#19076, microsoft/aspire#19826, microsoft/aspire#20070, microsoft/aspire#15671, microsoft/aspire#15969. - [x] **15. All 25 proposal dispositions:** listed below, including newer dashboard backports and four exclusions. Existing Sandbox inference coverage is retained rather than copied from a stale draft. - [ ] **16. Refresh generated API/catalog/Twoslash data from an official post-backport 13.6 build.** Existing `26473.12`/`a11eca96` data remains untouched. The newest public `dotnet9` feed package checked, `13.6.0-preview.1.26474.10` at `43496a2a306c81c862c947b11b4f4e5494b6fe08`, still has no Redis `WithRepl` in its actual package XML. Do not use 14.x, hand-edit declarations, or attribute source changes to older binaries. - [ ] **Validate the six REPL examples against that actual post-backport SDK and running clients.** Their new TypeScript fences are plain TypeScript, not annotated with unsupported Twoslash data. No existing diagnostics are allowlisted or suppressed; no generated API exports are fabricated. Enable Twoslash when the genuine catalog catches up. ### All 25 open proposal dispositions and provenance Text is selectively adapted from these proposals, not merged wholesale. #1778 and #1748 are authored by @sebastienros; the other proposals are authored by the Aspire repo bot. The table credits the associated product-change authors where supplied by the proposals. Existing PRs remain open and unchanged. | Docs PR | Release source / credited product author | Disposition | | --- | --- | --- | | #1778 | microsoft/aspire#19729 — @sebastienros | **Adopted:** canonical connection-string alias correction, including logical-first resolution and migration. | | #1771 | microsoft/aspire#20481 — @sebastienros | **Excluded:** flat polyglot feature keys are not in the audited release tip; no verified backport. Preserve release key names. | | #1770 | microsoft/aspire#20525 → microsoft/aspire#20548 — @mitchdenny | **Corrected/adopted:** command guides plus the still-current 13.6 article, which the proposal incorrectly treats as historical. | | #1769 | microsoft/aspire#20416 — @JamesNK | **Excluded:** brand hover change has no verified 13.6 membership/backport. | | #1768 | microsoft/aspire#20523 → microsoft/aspire#20546 — @JamesNK | **Adopted:** run pin/unpin preserves selector and current selection. | | #1766 | microsoft/aspire#20537 → microsoft/aspire#20541 — @mitchdenny | **Adopted:** terminal dock empty state. | | #1761 | microsoft/aspire#20490 → microsoft/aspire#20496 — @eerhardt | **Corrected:** graduation is 13.6, package remains prerelease, Blazor-specific exception retained. | | #1760 | microsoft/aspire#20436 — @eerhardt | **Excluded:** CLI net11/tools-any retarget is not in the audited release; no fallback-base inference. | | #1748 | microsoft/aspire#20131 — @sebastienros | **Adopted:** extend existing provisioning guide with service-specific models/lookups and projection limits. | | #1744 | microsoft/aspire#20337 → microsoft/aspire#20441 — @karolz-ms | **Adopted:** precise SDK-conditional multithreaded build coverage. | | #1740 | microsoft/aspire#20231 → microsoft/aspire#20419 — @mitchdenny | **Adapted:** all six guides; TypeScript-first tabs, source-verified lifecycle/security. Actual post-backport SDK/runtime gate is open above. | | #1738 | microsoft/aspire#20158 → microsoft/aspire#20405 — @karolz-ms | **Partly already covered / completed:** existing seven-skill catalog retained; add project migration guidance and correct command catalog/defaults. Do not misclassify the bundled skill as a companion tool. | | #1735 | microsoft/aspire#20334 — @karolz-ms | **Excluded:** enhanced startup errors are not in the audited release; no verified backport. | | #1731 | microsoft/aspire#19847 → microsoft/aspire#20391 — @eerhardt | **Corrected/adopted:** in-process NuGet and real authenticated-restore troubleshooting, not cache-command authentication. | | #1719 | microsoft/aspire#20299 → microsoft/aspire#20407 — @JamesNK | **Corrected/adopted:** cookie naming/scoping; identical names can collide but do not guarantee cross-dashboard cookie decryptability or shared sign-in. | | #1664 | microsoft/aspire#20011 — @maddymontaquila | **Adopted:** concise Azure environment icon release note. | | #1628 | microsoft/aspire#17742 — @davidfowl | **Adapted/expanded:** canonical Toolbox examples, consumer contract, role/index prerequisites, approval/security and concurrency limits. | | #1623 | microsoft/aspire#19810 — @mitchdenny | **Already covered:** current Sandbox guide/article already describe compute inference, explicit selection and external endpoints. Preserve that guidance while removing obsolete suppressions. | | #1620 | microsoft/aspire#19243 — @sebastienros | **Adapted:** AKS credential-before-Helm cleanup and destructive-operation warning; omit misleading ambient-context workaround. | | #1614 | microsoft/aspire#19870 — @sebastienros | **Adopted:** typed callback handle behavior in extension authoring and article. | | #1574 | microsoft/aspire#19430 — @mitchdenny | **Adapted:** canonical hostname inheritance, explicit-host precedence, catch-all default backend. | | #1570 | microsoft/aspire#19590 — @karolz-ms | **Adopted:** Dev Tunnel URL regression troubleshooting. | | #1565 | microsoft/aspire#19429 — @mitchdenny | **Corrected/adopted:** Helm embedded parameters with real `refExpr` and `addParameter(name, { value })`, not stringifying a handle or using an invalid actual-SDK overload. | | #1564 | microsoft/aspire#19026 — @karolz-ms | **Corrected/adopted:** C#/TypeScript Dotnet gateway walkthrough. Retain both experimental diagnostics; remove obsolete run-only restriction after microsoft/aspire#19997 publishing support. Avoid imported ambiguous API reference. | | #1499 | microsoft/aspire#19248 — @IEvangelist | **Adopted:** describe exact secret-value redaction and embedded-secret limit; release article already covered the fix. | ### Important source-verified corrections to proposals / earlier audit assumptions - [`BlazorGatewayExtensions.cs`](https://github.com/microsoft/aspire/blob/e8fd6fbb954f50ccd2e66479538392f65e13e71d/src/Aspire.Hosting.Blazor/BlazorGatewayExtensions.cs): `AddDotnetProjectBlazorGateway` and the Dotnet `WithBlazorClientApp` overload still carry `ASPIREDOTNETPROJECT001`; the class carries `ASPIREBLAZOR001`. They share `WithBlazorClientAppCore`/`WithBlazorApp` and the publish-companion path. Thus neither blanket diagnostic retirement nor the proposal's old run-only claim is correct. - [`SkillDefinition.cs`](https://github.com/microsoft/aspire/blob/e8fd6fbb954f50ccd2e66479538392f65e13e71d/src/Aspire.Cli/Agents/SkillDefinition.cs) sets bundled skills' `IsDefault=true`; [`AgentInitCommand.cs`](https://github.com/microsoft/aspire/blob/e8fd6fbb954f50ccd2e66479538392f65e13e71d/src/Aspire.Cli/Commands/AgentInitCommand.cs) selects the applicable catalog defaults for both flows. MCP has its own standalone-only binding. - [`TypeScriptAppHostToolchainResolver.cs`](https://github.com/microsoft/aspire/blob/e8fd6fbb954f50ccd2e66479538392f65e13e71d/src/Aspire.Cli/Projects/TypeScriptAppHostToolchainResolver.cs) is the source for Deno flags and certificate variable; guest Deno hosting is separate. - [`Radius README`](https://github.com/microsoft/aspire/blob/e8fd6fbb954f50ccd2e66479538392f65e13e71d/src/Aspire.Hosting.Radius/README.md) supplies the resource-specific credential rules and publish diagnostics, not assumptions about local endpoints. ## Third-party links and affiliations <!-- List third-party links and disclose material affiliations. --> Links point to official Microsoft Learn, VS Code Marketplace debugger extensions, Rust/Cargo/Bacon documentation, Radius documentation, and source repositories. No sponsorship, commercial endorsement, or affiliation claim is introduced. Maintainers should supply any personal affiliation disclosure required by policy; automation has not inferred one. ## Validation <!-- List the checks you ran or explain why validation isn't needed. --> - **97 passing focused unit checks** across API-reference authoring/rendering, Twoslash blocks, file-tree formatting, CLI configuration schema, SEO lengths, and resource catalog. - **82 passing structured-data checks**, including exact integration mapping uniqueness and page resolution. - **11 C# samples compile**, zero warnings/errors, using genuine `13.6.0-preview.1.26473.12` packages. Scope: Rust, Connector Namespace, Radius, Toolbox, inline CSI, Helm, Blazor gateway, and provisioning. `Projects.Api/Worker/Client` use compile-only `IProjectMetadata` stand-ins; no claim of running those apps or provisioning cloud resources. - **10 TypeScript samples pass `tsc`** under `strict`, `NodeNext`, and `ES2022` against three **unmodified actual SDK files**, not just the site's declaration bundle. The fixture uses the exact `e8fd6fbb` release `AtsCapabilityScanner` and genuine `26473.12` TypeSystem/code-generator/integration binaries, whose informational source is `a11eca96`. This is an isolated local generation fixture, **not** a claim that official CLI generation or a new packaged release was tested. An attempted restore with the older handed-off local CLI could not discover an AppHost server; the bounded direct generator fixture was used instead. - The SDK scan is **not globally warning-free**: it reports a Radius `withContainerImage` collision on `CSharpAppResource` and an App Configuration `createRoleAssignment` overload collision. None of the compiled examples calls those colliding methods; the warnings are retained in evidence, not suppressed, and no generated declarations were edited. - Browser: Connector Namespace, Radius, both Rust pages, Foundry hosting, and What's new return **HTTP 200**, correct headings, and no rendered Twoslash errors. New guide/article page-local anchors and the cross-page Blazor anchor resolve. Connector/Radius mobile layouts have no horizontal overflow; Connector language-tab interaction works. Standalone Astro preview emits expected `/api/live` 404s because StaticHost is not running. - `git diff --check` passes. No production `pnpm build`, cloud deployment, REPL runtime session, full product suite, or blanket validation of every pre-existing example was performed. - Generated C#/TypeScript API data, declaration bundles, integration catalogs, image catalogs, and contributor data are unchanged. Only the authored package-to-guide mapping is updated. **Before merging:** complete the two packaging/REPL checkboxes above, inspect CI, and obtain human review. This PR intentionally does not close or merge the source documentation proposals. --------- Co-authored-by: David Pine <7679720+IEvangelist@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>


Description
Adds first-class Microsoft Foundry Toolbox support to
Aspire.Hosting.Foundry. Toolboxes are Foundry data-plane resources that bundle tools behind one MCP endpoint; they do not have an ARM or Bicep representation.Usage
Existing Toolboxes can be validated without mutation using
RunAsExisting(),PublishAsExisting(), orAsExisting(). A specific immutable version can be pinned throughAddToolboxoptions.MCP endpoints must be reachable from the Foundry data plane over HTTPS. Localhost, loopback, URI credentials, inline headers, and connection-authenticated MCP tools are not supported. MCP approval policies are discovery metadata; consuming applications remain responsible for enforcing approval before invocation.
Deployment behavior
Connection properties
UriProjectEndpointNameApiVersionVersionFoundryFeaturesFoundry-Featuresrequest-header valueAuthorizationScopeCoverage
swedencentralthat provisions Web Search, MCP, and Azure AI Search tools; validates persisted metadata and Search index configuration; performs an authenticated MCPinitialize/tools/listhandshake; and verifies a second deployment preserves the default version, hash, and version count.Checklist
<remarks />and<code />elements on your triple slash comments?