microsoft/aspire · error · InvalidOperationException

MCP tool ' ' must resolve to a Foundry-reachable absolute…

Error message

MCP tool '{Name}' must resolve to a Foundry-reachable absolute HTTPS endpoint.

What it means

After resolving to a non-empty string, the endpoint must be an absolute URI that IsFoundryReachableHttpsEndpoint accepts: https scheme, no user info, non-loopback, and not localhost/.localhost. Microsoft Foundry cannot reach a developer-local server, so the integration rejects such endpoints with this InvalidOperationException before building the MCP wire JSON.

Solutions

  1. Deploy or host the MCP server at a publicly reachable HTTPS URL and use that as the endpoint.
  2. Change the scheme to https and remove any user info from the URL.
  3. Verify the string is a full absolute URI (e.g. https://host/mcp), not a relative path or bare hostname.
  4. For local testing, use a tunnel (dev tunnels/ngrok) that exposes a public HTTPS URL.

Example fix

// before
ReferenceExpression.Create($"http://localhost:8080/mcp")
// after
ReferenceExpression.Create($"https://my-mcp.example.com/mcp")
Defensive patterns

Strategy: validation

Validate before calling

if (Uri.TryCreate(endpoint, UriKind.Absolute, out var uri)
    && uri.Scheme == Uri.UriSchemeHttps
    && string.IsNullOrEmpty(uri.UserInfo)
    && !uri.IsLoopback
    && !uri.Host.EndsWith("localhost", StringComparison.OrdinalIgnoreCase))
{ /* endpoint is Foundry-reachable */ }

Type guard

static bool IsFoundryReachable(Uri u) =>
    u.Scheme == Uri.UriSchemeHttps && string.IsNullOrEmpty(u.UserInfo) &&
    !u.IsLoopback && !u.Host.TrimEnd('.').EndsWith("localhost", StringComparison.OrdinalIgnoreCase);

Try / catch

try { await definition.ResolveAsync(ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Foundry-reachable absolute HTTPS endpoint"))
{ logger.LogError("Endpoint '{Endpoint}' must be a public absolute HTTPS URL.", endpoint); }

Prevention

When it happens

Trigger: Passing an http:// URL, a relative or malformed URI, a URL with embedded user:password, or a http://localhost / 127.0.0.1 / *.localhost endpoint to FoundryToolboxMcpToolDefinition.

Common situations: Pointing the MCP tool at a locally running MCP server during development; forgetting the 's' in https; supplying a path-only string like 'myserver/mcp' instead of a full absolute URL; credentials embedded in the URL.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/8ef8f73bf45f1f7f. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs:156

    public string ServerLabel { get; }

    public string? ServerDescription { get; }

    internal ResolvedFoundryToolboxMcpApprovalPolicy? ApprovalPolicy { get; }

    internal override async ValueTask<ResolvedFoundryToolboxTool> ResolveAsync(CancellationToken cancellationToken)
    {
        var endpoint = await EndpointExpression.GetValueAsync(cancellationToken).ConfigureAwait(false);
        if (string.IsNullOrEmpty(endpoint))
        {
            throw new InvalidOperationException(
                $"MCP tool '{Name}' does not have a resolvable endpoint URI.");
        }

        if (!Uri.TryCreate(endpoint, UriKind.Absolute, out var endpointUri) ||
            !IsFoundryReachableHttpsEndpoint(endpointUri))
        {
            throw new InvalidOperationException(
                $"MCP tool '{Name}' must resolve to a Foundry-reachable absolute HTTPS endpoint.");
        }

        // Build the OpenAI Responses "mcp" tool wire JSON by hand and read it back as a
        // ProjectsAgentTool. See the comment on FoundryToolboxWebSearchToolDefinition for the
        // underlying cross-ALC System.ClientModel version mismatch that makes the natural
        // `ResponseTool.CreateMcpTool(...).AsAgentTool()` round-trip throw in the polyglot
        // (e.g. JavaScript/TypeScript) AppHostServer host process. Constructing the JSON
        // ourselves keeps everything inside types that are consistent across the integration's
        // ALC (BCL + Azure.AI.Projects.Agents + that ALC's copy of System.ClientModel).
        //
        // OpenAI Responses "mcp" tool wire shape:
        //   {
        //     "type": "mcp",
        //     "server_label": "<required>",
        //     "server_url":   "<absolute uri>" // required for hosted MCP
        //   }
        // See https://platform.openai.com/docs/api-reference/responses/create#responses-create-tools

View on GitHub (pinned to 25830f84bd)