[BUG] NO_PROXY host, suffix, and CIDR entries do not bypass the configured proxy
- Dominant language
- C#
- Stars
- 3.7k
- Forks
- 624
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 220
Description
### Describe the bug
Azure MCP honors `HTTP_PROXY` / `HTTPS_PROXY`, but its custom `NO_PROXY` handling is incompatible with standard hostname, leading-dot suffix, and CIDR entries.
`AddHttpClientServices` reads `ALL_PROXY`, `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. `HttpClientFactoryConfigurator.CreateProxy` then creates a `WebProxy`, converts each `NO_PROXY` entry with `ConvertGlobToRegex`, and assigns the result to `WebProxy.BypassList`:
- https://github.com/microsoft/mcp/blob/main/core/Microsoft.Mcp.Core/src/Extensions/HttpClientServiceCollectionExtensions.cs
- https://github.com/microsoft/mcp/blob/main/core/Microsoft.Mcp.Core/src/Services/Http/HttpClientFactoryConfigurator.cs
The conversion anchors the supplied entry itself. For example:
```text
api.loganalytics.io -> ^api\.loganalytics\.io$
.ods.opinsights.azure.com -> ^\.ods\.opinsights\.azure\.com$
10.0.0.0/8 -> ^10\.0\.0\.0/8$
```
However, .NET `WebProxy.BypassList` contains regular expressions evaluated against a formatted URL such as `https://api.loganalytics.io` or `https://workspace.ods.opinsights.azure.com`, not only `Uri.Host`. Therefore the exact-host and standard leading-dot suffix expressions above do not match. CIDRs are treated as literal strings and also do not match addresses in their range.
A raw glob such as `*.ods.opinsights.azure.com` may appear to work accidentally because its leading `.*` can consume the URL scheme and hostname prefix, but standard `NO_PROXY` implementations use `.ods.opinsights.azure.com` for suffix matching. Callers also cannot work around the mismatch by supplying a `WebProxy` URL regex because `ConvertGlobToRegex` escapes regex metacharacters before assignment.
This custom parser also bypasses the platform `HttpEnvironmentProxy` implementation. .NET 11 added native IPv4/IPv6 CIDR support for `NO_PROXY` in https://github.com/dotnet/runtime/pull/131397, but current Azure MCP still performs its own conversion. Azure MCP reads only uppercase variables as well, while .NET checks lowercase names first on case-sensitive platforms.
The implementation is present in the `Azure.Mcp.Server-2.0.1` tag and remains on current `main`.
### Expected behavior
Standard `NO_PROXY` values should bypass the proxy:
- `api.loganalytics.io` for that exact hostname
- `.ods.opinsights.azure.com` for the domain and its subdomains
- `10.0.0.0/8` for IP destinations within that network when supported by the target runtime
- lowercase and uppercase environment names according to platform/.NET precedence
Preferably Azure MCP should delegate environment-proxy parsing to .NET instead of maintaining a divergent parser. If a custom proxy remains necessary, it should implement the same hostname, suffix, CIDR, casing, and precedence semantics explicitly.
### Actual behavior
With `HTTPS_PROXY` configured, requests covered by exact-host, standard leading-dot suffix, or CIDR `NO_PROXY` entries still go through the proxy.
Observed examples include:
```text
api.loganalytics.io
api.loganalytics.azure.com
api.applicationinsights.io
.ods.opinsights.azure.com
10.0.0.0/8
```
### Reproduction Steps
1. Start Azure MCP on Linux with a proxy that logs requests:
```bash
HTTP_PROXY=http://proxy.example:3128 \
HTTPS_PROXY=http://proxy.example:3128 \
NO_PROXY=api.loganalytics.io,.ods.opinsights.azure.com,10.0.0.0/8 \
npx -y @azure/mcp@2.0.1 server start --namespace monitor --mode all --read-only
```
2. Invoke Monitor tools that call Log Analytics or Application Insights, or otherwise exercise a destination covered by the configured entries.
3. Observe those requests reaching the proxy despite the matching `NO_PROXY` entries.
4. The behavior follows directly from testing the generated regexes against the URL strings used by `WebProxy.BypassList`.
### Environment
- Hosting platform: Linux container / Azure sandbox
- Azure MCP: `@azure/mcp@2.0.1`
- Azure MCP target framework at that tag: .NET 10
- Source review confirms current `main` retains the same custom parser
- Relevant runtime CIDR change: dotnet/runtime#131397, targeting .NET 11
Contributor guide
Assessment
This issue has not been assessed yet.