Migrate Foundry MCP server to use external integration.#1771
Migrate Foundry MCP server to use external integration.#1771g2vinay wants to merge 5 commits intomicrosoft:mainfrom
Conversation
- CustomChainedCredential: add forceBrowserFallback param, suppressed when AZURE_TOKEN_CREDENTIALS=prod; enables InteractiveBrowserCredential fallback only in user-identity modes (SingleIdentityTokenCredentialProvider) - SafeTokenCredential: add normalizeScopes=true for all 8 non-MSAL credentials (EnvironmentCredential, WorkloadIdentity, ManagedIdentity, VisualStudio, VisualStudioCode, AzureCli, AzurePowerShell, AzureDeveloperCli) Converts https://mcp.ai.azure.com/Foundry.Mcp.Tools to https://mcp.ai.azure.com/.default so resource-based credential types receive the correct scope format; InteractiveBrowserCredential is unwrapped and receives the verbatim MSAL permission scope - Microsoft.Mcp.slnx and Azure.Mcp.Server.slnx: remove deleted Azure.Mcp.Tools.Foundry project references
There was a problem hiding this comment.
Pull request overview
This PR migrates the Foundry toolset from an in-process implementation (tools/Azure.Mcp.Tools.Foundry) to an external MCP integration hosted at https://mcp.ai.azure.com, and updates Azure MCP’s auth plumbing so the registry HTTP client can obtain tokens for that external server (including optional interactive fallback and scope normalization).
Changes:
- Removed the in-repo Foundry tool project (source, options/models, unit/live tests, test infra, and solution entries).
- Added a
foundryexternal server entry toregistry.jsonand updated discovery tests accordingly. - Extended outbound auth support (new
AccessTokenHandlerctor,CustomChainedCredentialinteractive fallback flag, andSafeTokenCredentialscope normalization) and updated DI wiring for registry HTTP clients.
Reviewed changes
Copilot reviewed 111 out of 111 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/Azure.Mcp.Tools.Foundry/tests/test-resources.bicep | Deleted Foundry test infra deployment template. |
| tools/Azure.Mcp.Tools.Foundry/tests/test-resources-post.ps1 | Deleted Foundry post-deploy hook script. |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ThreadListCommandTests.cs | Deleted Foundry unit tests (threads list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ThreadGetMessagesCommandTests.cs | Deleted Foundry unit tests (thread messages). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ThreadCreateCommandTests.cs | Deleted Foundry unit tests (thread create). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ResourceGetCommandTests.cs | Deleted Foundry unit tests (resource get/list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/OpenAiModelsListCommandTests.cs | Deleted Foundry unit tests (OpenAI models list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/OpenAiEmbeddingsCreateCommandTests.cs | Deleted Foundry unit tests (embeddings). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/OpenAiCompletionsCreateCommandTests.cs | Deleted Foundry unit tests (completions). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/OpenAiChatCompletionsCreateCommandTests.cs | Deleted Foundry unit tests (chat completions metadata). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ModelsListCommandTests.cs | Deleted Foundry unit tests (catalog models list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/ModelDeploymentCommandTests.cs | Deleted Foundry unit tests (model deploy). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/KnowledgeIndexSchemaCommandTests.cs | Deleted Foundry unit tests (knowledge schema). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/KnowledgeIndexListCommandTests.cs | Deleted Foundry unit tests (knowledge list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/FoundryServiceEndpointValidationTests.cs | Deleted Foundry endpoint validation tests (SSRF/host allowlist). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/DeploymentsListCommandTests.cs | Deleted Foundry unit tests (deployments list). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/Azure.Mcp.Tools.Foundry.UnitTests.csproj | Deleted Foundry unit test project file. |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/AgentsGetSdkCodeSampleCommandTests.cs | Deleted Foundry unit tests (SDK sample). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.UnitTests/AgentsCreateCommandTests.cs | Deleted Foundry unit tests (agent create). |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.LiveTests/assets.json | Deleted recorded-test assets metadata for Foundry live tests. |
| tools/Azure.Mcp.Tools.Foundry/tests/Azure.Mcp.Tools.Foundry.LiveTests/Azure.Mcp.Tools.Foundry.LiveTests.csproj | Deleted Foundry live test project file. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/Models/CognitiveServicesSku.cs | Deleted Foundry internal service model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/Models/CognitiveServicesAccountDeploymentScaleSettings.cs | Deleted Foundry internal service model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/Models/CognitiveServicesAccountDeploymentProperties.cs | Deleted Foundry internal service model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/Models/CognitiveServicesAccountDeploymentModel.cs | Deleted Foundry internal service model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/Models/CognitiveServicesAccountDeploymentData.cs | Deleted Foundry internal service model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Services/IFoundryService.cs | Deleted Foundry service interface. |
| tools/Azure.Mcp.Tools.Foundry/src/Resources/AgentSdkSamples/typescript.md | Deleted embedded SDK sample docs. |
| tools/Azure.Mcp.Tools.Foundry/src/Resources/AgentSdkSamples/python.md | Deleted embedded SDK sample docs. |
| tools/Azure.Mcp.Tools.Foundry/src/Resources/AgentSdkSamples/csharp.md | Deleted embedded SDK sample docs. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Thread/ThreadListResult.cs | Deleted Foundry options/result model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Thread/ThreadListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Thread/ThreadGetMessagesOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Thread/ThreadCreateResult.cs | Deleted Foundry options/result model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Thread/ThreadCreateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/ResourceGetOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/OpenAiModelsListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/OpenAiEmbeddingsCreateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/OpenAiCompletionsCreateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/OpenAiChatCompletionsCreateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/ModelsListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/ModelDeploymentOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/KnowledgeIndexSchemaOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/KnowledgeIndexListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/DeploymentsListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Models/BaseKnowledgeIndexOptions.cs | Deleted Foundry options base type. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/FoundryOptionDefinitions.cs | Deleted Foundry CLI option definitions. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsQueryAndEvaluateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsListOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsGetSdkSampleOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsEvaluateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsCreateOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Options/Agents/AgentsConnectOptions.cs | Deleted Foundry options model. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ThreadGetMessagesResult.cs | Deleted Foundry response model. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/OpenAiModelsListModels.cs | Deleted Foundry response models. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelInformation.cs | Deleted Foundry catalog model type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelDeploymentResult.cs | Deleted Foundry deployment response model. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelDeploymentInformation.cs | Deleted Foundry model metadata type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelCatalogResponse.cs | Deleted Foundry catalog response type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelCatalogRequest.cs | Deleted Foundry catalog request type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ModelCatalogFilter.cs | Deleted Foundry catalog filter type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/KnowledgeIndexSchema.cs | Deleted Foundry knowledge schema type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/KnowledgeIndexInformation.cs | Deleted Foundry knowledge index type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/EmbeddingModels.cs | Deleted Foundry embedding response types. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/CompletionModels.cs | Deleted Foundry completion response types. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/ChatCompletionModels.cs | Deleted Foundry chat completion response types. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AiResourceInformation.cs | Deleted Foundry AI resource models. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentsQueryAndEvaluateResult.cs | Deleted Foundry agent evaluation result type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentsGetSdkCodeSampleResult.cs | Deleted Foundry SDK sample result type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentsEvaluateResult.cs | Deleted Foundry evaluation result type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentsCreateResult.cs | Deleted Foundry agent create result type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentsConnectResult.cs | Deleted Foundry agent connect result type. |
| tools/Azure.Mcp.Tools.Foundry/src/Models/AgentFileSearchResult.cs | Deleted Foundry internal helper model. |
| tools/Azure.Mcp.Tools.Foundry/src/GlobalUsings.cs | Deleted Foundry global usings file. |
| tools/Azure.Mcp.Tools.Foundry/src/FoundrySetup.cs | Deleted Foundry area setup and command registration. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ThreadListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ThreadGetMessagesCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ThreadCreateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ResourceGetCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/OpenAiModelsListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/OpenAiEmbeddingsCreateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/OpenAiCompletionsCreateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/OpenAiChatCompletionsCreateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ModelsListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/ModelDeploymentCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/KnowledgeIndexSchemaCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/KnowledgeIndexListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/FoundryJsonContext.cs | Deleted Foundry STJ source-gen context. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/DeploymentsListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsQueryAndEvaluate.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsListCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsGetSdkSampleCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsEvaluateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsCreateCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Commands/AgentsConnectCommand.cs | Deleted Foundry command implementation. |
| tools/Azure.Mcp.Tools.Foundry/src/Azure.Mcp.Tools.Foundry.csproj | Deleted Foundry tool project definition. |
| tools/Azure.Mcp.Tools.Foundry/src/AssemblyInfo.cs | Deleted test visibility attributes tied to Foundry test projects. |
| servers/Azure.Mcp.Server/src/Program.cs | Removed in-process Foundry area registration. |
| servers/Azure.Mcp.Server/docs/azmcp-commands.md | Removed Foundry CLI docs section and Foundry references in best-practices text. |
| servers/Azure.Mcp.Server/Azure.Mcp.Server.slnx | Removed Foundry tool projects from Azure server solution. |
| core/Microsoft.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs | Added forceBrowserFallback and scope normalization support via SafeTokenCredential. |
| core/Microsoft.Mcp.Core/src/Areas/Server/Resources/registry.json | Added external foundry registry entry pointing to https://mcp.ai.azure.com with OAuth scopes. |
| core/Microsoft.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json | Removed Foundry tool mappings from consolidated tool list/metadata. |
| core/Microsoft.Mcp.Core/src/Areas/Server/RegistryServerServiceCollectionExtensions.cs | Adjusted registry HttpClient auth handler wiring (special-casing single-identity provider). |
| core/Microsoft.Mcp.Core/src/AccessTokenHandler.cs | Added TokenCredential-based constructor for outbound auth handler. |
| core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Areas/Server/Commands/Discovery/RegistryDiscoveryStrategyTests.cs | Added tests asserting foundry registry server discovery and properties. |
| core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Areas/Server/CommandFactoryHelpers.cs | Removed Foundry setup from command factory test helper. |
| Microsoft.Mcp.slnx | Removed Foundry tool projects from root solution. |
| .github/CODEOWNERS | Removed Foundry tool path ownership entries. |
| private static string NormalizeScope(string scope) => | ||
| scope.EndsWith("/.default", StringComparison.OrdinalIgnoreCase) | ||
| ? scope | ||
| : $"{new Uri(scope).GetLeftPart(UriPartial.Authority)}/.default"; | ||
|
|
||
| private TokenRequestContext MaybeNormalize(TokenRequestContext ctx) => | ||
| _normalizeScopes | ||
| ? new TokenRequestContext([.. ctx.Scopes.Select(NormalizeScope)], ctx.ParentRequestId, ctx.Claims, ctx.TenantId, ctx.IsCaeEnabled) | ||
| : ctx; |
There was a problem hiding this comment.
SafeTokenCredential scope normalization can throw (e.g., new Uri(scope) / invalid scope format) before entering the try/catch that wraps errors as CredentialUnavailableException. That would bypass chaining behavior and can fail the whole token acquisition path. Consider making normalization non-throwing (e.g., Uri.TryCreate / catch UriFormatException) and fall back to the original scope when it can’t be normalized.
| // Only add InteractiveBrowserCredential as fallback when: | ||
| // 1. AZURE_TOKEN_CREDENTIALS is not set (default behavior) | ||
| // 2. AZURE_TOKEN_CREDENTIALS explicitly requests it | ||
| // 3. AZURE_TOKEN_CREDENTIALS="dev" (development credentials with interactive fallback) | ||
| // 4. forceBrowserFallback=true AND AZURE_TOKEN_CREDENTIALS is not "prod" | ||
| // (registry server callers want interactive fallback for local/hosting-identity scenarios, | ||
| // but must respect "prod" which means headless/CI — no browser popup) | ||
| // Do NOT add it for "prod" or specific credential names (user wants only those credentials) | ||
| bool shouldAddBrowserFallback = !hasExplicitCredentialSetting || | ||
| bool isProdMode = tokenCredentials?.Equals("prod", StringComparison.OrdinalIgnoreCase) ?? false; | ||
| bool shouldAddBrowserFallback = (!isProdMode && forceBrowserFallback) || | ||
| !hasExplicitCredentialSetting || | ||
| (tokenCredentials?.Equals("dev", StringComparison.OrdinalIgnoreCase) ?? false) || | ||
| (tokenCredentials?.Equals("interactivebrowsercredential", StringComparison.OrdinalIgnoreCase) ?? false); |
There was a problem hiding this comment.
The XML remarks and inline comment state InteractiveBrowserCredential is not added when AZURE_TOKEN_CREDENTIALS targets a specific credential name, but the new forceBrowserFallback path currently overrides that (unless AZURE_TOKEN_CREDENTIALS=prod). Either update the documentation/comments to reflect the new behavior, or tighten the shouldAddBrowserFallback condition so it still honors the “specific credential only” contract.
| // Should have exactly 3 servers in registry | ||
| Assert.Equal(3, serverIds.Count); |
There was a problem hiding this comment.
This test hard-codes the total number of registry servers (Assert.Equal(3, serverIds.Count)), which will become brittle as soon as another server is added to registry.json. Prefer asserting presence of the expected IDs (already done) without asserting an exact count, or assert >= with a clear reason if ordering/size is important.
| // Should have exactly 3 servers in registry | |
| Assert.Equal(3, serverIds.Count); | |
| // Intentionally do not assert total count to avoid brittleness as registry.json evolves. |
| // 4. forceBrowserFallback=true AND AZURE_TOKEN_CREDENTIALS is not "prod" | ||
| // (registry server callers want interactive fallback for local/hosting-identity scenarios, | ||
| // but must respect "prod" which means headless/CI — no browser popup) | ||
| // Do NOT add it for "prod" or specific credential names (user wants only those credentials) |
There was a problem hiding this comment.
If tokenCredentials is a specific credential (but not "prod") and forceBrowserFallback is true the browser fallback will be added now.
| /// <para> | ||
| /// It is NOT added when: | ||
| /// - AZURE_TOKEN_CREDENTIALS="prod" (production credentials only, fail fast if unavailable) | ||
| /// - AZURE_TOKEN_CREDENTIALS=specific credential name (user wants only that credential, fail fast) |
There was a problem hiding this comment.
This doc string needs to be updated to reflect the new branching condition to determine whether to add the browser fallback.
This PR migrates Microsoft Foundry from in-process tool files to the external MCP server
at
https://mcp.ai.azure.com, then adds the authentication plumbing needed for the Azure MCPserver to call that external server on the user's behalf.
Changes:
Foundry → external MCP server (
registry.json)All Foundry source files (commands, services, options, models, tests, setup) have been deleted.
Instead,
registry.jsonnow contains a"foundry"entry that points the runtime at the hostedserver:
The Foundry project references have also been removed from both
Microsoft.Mcp.slnxandAzure.Mcp.Server.slnx.AccessTokenHandler—TokenCredential-based constructorA second constructor was added so the registry HTTP client can be wired directly to a
TokenCredentialinstance rather than always going throughIAzureTokenCredentialProvider:CustomChainedCredential—forceBrowserFallbackparameterA new
forceBrowserFallbackconstructor parameter allows callers to opt intoInteractiveBrowserCredentialas a last resort without requiringAZURE_TOKEN_CREDENTIALStobe unset globally. The flag is suppressed when
AZURE_TOKEN_CREDENTIALS=prod, so CI/headlessenvironments are never interrupted by a browser popup.
SafeTokenCredential—normalizeScopesparameterNon-MSAL credentials (
AzureCliCredential,ManagedIdentityCredential, etc.) use aresource-based auth model: they expect a scope of the form
https://host/.defaultand strip the/.defaultsuffix internally to derive the resource URL. They cannot handle arbitrary MSALpermission scopes like
https://mcp.ai.azure.com/Foundry.Mcp.Tools.SafeTokenCredentialnow acceptsnormalizeScopes: true, which transparently converts anynon-
/.defaultscope to itsresource/.defaultform before forwarding to the inner credential.