Skip to content

Switch from Environment.GetEnvironmentVariable to IConfiguration#1704

Draft
srnagar wants to merge 3 commits intomicrosoft:mainfrom
srnagar:envvar-config
Draft

Switch from Environment.GetEnvironmentVariable to IConfiguration#1704
srnagar wants to merge 3 commits intomicrosoft:mainfrom
srnagar:envvar-config

Conversation

@srnagar
Copy link
Member

@srnagar srnagar commented Feb 11, 2026

…Configuration

What does this PR do?

[Provide a clear, concise description of the changes]

[Any additional context, screenshots, or information that helps reviewers]

GitHub issue number?

[Link to the GitHub issue this PR addresses]

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Updated servers/Azure.Mcp.Server/CHANGELOG.md and/or servers/Fabric.Mcp.Server/CHANGELOG.md for product changes (features, bug fixes, UI/UX, updated dependencies)
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes using script at eng/scripts/Process-PackageReadMe.ps1. See Package README
    • Updated command list in /servers/Azure.Mcp.Server/docs/azmcp-commands.md and/or /docs/fabric-commands.md
    • Run .\eng\scripts\Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For tools with new names, including new tools or renamed tools, update consolidated-tools.json
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated test prompts in /servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

@srnagar srnagar changed the title initial commit to switch from Environment.GetEnvironmentVariable to I… Switch from Environment.GetEnvironmentVariable to IConfiguration Feb 11, 2026
@github-actions github-actions bot added the tools-Azd Azure Developer CLI related label Feb 11, 2026
var env = Environment.GetEnvironmentVariables()
.Cast<System.Collections.DictionaryEntry>()
.ToDictionary(e => (string)e.Key, e => (string?)e.Value);
// Merge current configuration values (includes environment variables) with serverInfo.Env (serverInfo.Env overrides)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IConfiguration comprises of a lot more than just environment variables. Also includes things like appsettings.json, other configuration providers. Is this what you want?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the intent here is for serverInfo.Env to take precedence over everything else. So, yes, this should still work as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also argue that it may not be appropriate for azmcp's json config to appear as transitive config at the environment variable level for another server we start.

If environment variables have higher priority than json config. We'd be elevating azmcp's json config over the other server's json config

.Returns(Substitute.For<HttpClient>());
return new RegistryServerProvider(id, serverInfo, httpClientFactory);
var configuration = new ConfigurationBuilder().AddEnvironmentVariables().Build();
return new RegistryServerProvider(id, serverInfo, httpClientFactory, configuration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 100% behind replacing our environment variable pulls with DI, but passing IConfiguration into the business layer feels like an antipattern. It's hiding the real dependency and letting some deep logic decide that it now cares about a new json or environment variable config without "informing" the startup.

I'd much prefer we use the options pattern over raw IConfiguration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Program.cs and ServiceCollection/Provider would be responsible for converting the state of the world at program start into strongly typed options classes. Everything below program.cs would deal with strongly typed POCOs.

We would just need to decide how coupled our option classes would be. We could have:
RegistryServerProvider depend on IOptions<RegistryServerProviderOptions>

Or we could have a more aggregate options class that serves any of our internal classes that needed config:

RegistryServerProvider depends on IOptions<AzureMcpServerOptions>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could punt on IOptions and just replace the non-mockable Environment.GetEnvironmentVariable with IEnvironmentVariables.Get

// Merge current configuration values (includes environment variables) with serverInfo.Env (serverInfo.Env overrides)
var env = _configuration.AsEnumerable()
.Where(kvp => kvp.Value is not null)
.ToDictionary(kvp => kvp.Key, kvp => (string?)kvp.Value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this would round trip correctly. While IConfig and environment variables are both string/string maps, their key serialization scheme is different.

When IConfiguration is built from environment variables, it expects a hierarchy delimiter of __ or _, but that's converted to IConfig's normal hierarchy delimiter of : internally.

To round trip, you'd have to convert all : in each key to __

https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration-providers#environment-variable-configuration-provider

The : delimiter doesn't work with environment variable hierarchical keys on all platforms. For example, the : delimiter is not supported by Bash. The double underscore (__), which is supported on all platforms, automatically replaces any : delimiters in environment variables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools-Azd Azure Developer CLI related

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

3 participants