diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs
index 7bad1661e7..4c9862ae11 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs
@@ -11,8 +11,7 @@
namespace Azure.Mcp.Core.Services.Azure.Authentication;
///
-/// A custom token credential that chains multiple Azure credentials with a broker-enabled instance of
-/// InteractiveBrowserCredential to provide a seamless authentication experience.
+/// A custom token credential that chains multiple Azure credentials with optional browser-enabled authentication.
///
///
/// The credential chain behavior can be controlled via the AZURE_TOKEN_CREDENTIALS environment variable:
@@ -26,7 +25,7 @@ namespace Azure.Mcp.Core.Services.Azure.Authentication;
/// Special behavior: When running in VS Code context (VSCODE_PID environment variable is set) and AZURE_TOKEN_CREDENTIALS is not explicitly specified,
/// Visual Studio Code credential is automatically prioritized first in the chain.
///
-/// After the credential chain, Interactive Browser Authentication with Identity Broker is always added as the final fallback.
+/// Interactive Browser Authentication is automatically disabled in headless environments (no DISPLAY/Wayland, CI/CD, containers, Windows services).
///
public class CustomChainedCredential(string? tenantId = null, ILogger? logger = null) : TokenCredential
{
@@ -56,6 +55,71 @@ private static bool ShouldUseOnlyBrokerCredential()
return EnvironmentHelpers.GetEnvironmentVariableAsBool(OnlyUseBrokerCredentialEnvVarName);
}
+ private static bool IsHeadlessEnvironment()
+ {
+ bool nonInteractive = !Environment.UserInteractive;
+
+ // ---------- OS-scoped heuristics ----------
+ bool noDisplay = false;
+ bool inDocker = false, inK8s = false, cgroupContainer = false;
+
+ if (OperatingSystem.IsLinux())
+ {
+ string? display = Environment.GetEnvironmentVariable("DISPLAY");
+ string? wayland = Environment.GetEnvironmentVariable("WAYLAND_DISPLAY");
+ string? xdg = Environment.GetEnvironmentVariable("XDG_SESSION_TYPE");
+ noDisplay = string.IsNullOrEmpty(display) &&
+ string.IsNullOrEmpty(wayland) &&
+ string.IsNullOrEmpty(xdg);
+
+ try { inDocker = File.Exists("/.dockerenv"); } catch { /* ignore */ }
+ try { inK8s = File.Exists("/var/run/secrets/kubernetes.io/serviceaccount/token"); } catch { /* ignore */ }
+ try {
+ cgroupContainer =
+ FileContainsAny("/proc/1/cgroup", "docker", "kubepods", "containerd") ||
+ FileContainsAny("/proc/self/mountinfo", "containers");
+ } catch { /* ignore */ }
+ }
+ // Note: On macOS, skip DISPLAY/Wayland checks. On Windows, skip /proc and container-file checks.
+
+ // ---------- CI/CD ----------
+ bool inCI =
+ IsEnvTrue("CI") ||
+ IsEnvTrue("GITHUB_ACTIONS") ||
+ IsEnvTrue("GITLAB_CI") ||
+ IsEnvTrue("AZP_CI") ||
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TEAMCITY_VERSION")) ||
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_NUMBER")) ||
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TF_BUILD"));
+
+ // ---------- Windows service hint ----------
+ bool winServiceLike = OperatingSystem.IsWindows() &&
+ string.Equals(Environment.GetEnvironmentVariable("SESSIONNAME"), "Services", StringComparison.OrdinalIgnoreCase);
+
+ return nonInteractive || noDisplay || inCI || inDocker || inK8s || cgroupContainer || winServiceLike;
+ }
+
+ // helpers
+ private static bool IsEnvTrue(string key)
+ {
+ var v = Environment.GetEnvironmentVariable(key);
+ return v != null && (v.Equals("1", StringComparison.OrdinalIgnoreCase)
+ || v.Equals("true", StringComparison.OrdinalIgnoreCase)
+ || v.Equals("yes", StringComparison.OrdinalIgnoreCase));
+ }
+
+ private static bool FileContainsAny(string path, params string[] needles)
+ {
+ try
+ {
+ var txt = File.ReadAllText(path);
+ foreach (var n in needles)
+ if (txt.IndexOf(n, StringComparison.OrdinalIgnoreCase) >= 0) return true;
+ }
+ catch { /* ignore */ }
+ return false;
+ }
+
private static TokenCredential CreateCredential(string? tenantId, ILogger? logger = null)
{
string? authRecordJson = Environment.GetEnvironmentVariable(AuthenticationRecordEnvVarName);
@@ -92,7 +156,16 @@ private static TokenCredential CreateCredential(string? tenantId, ILogger