microsoft/aspire · error · InvalidOperationException
MCP tool ' ' does not have a resolvable endpoint URI.
Error message
MCP tool '{Name}' does not have a resolvable endpoint URI. What it means
FoundryToolboxMcpToolDefinition.ResolveAsync evaluates the endpoint ReferenceExpression for the MCP tool. If the expression resolves to null or an empty string, the integration throws this InvalidOperationException because a hosted MCP tool cannot be registered without a server URL. It fails fast at tool resolution time rather than producing a wire payload the Foundry service would reject.
Solutions
- Check that the endpoint expression's source resource actually exposes the endpoint (add WithEndpoint/WithHttpEndpoint if missing).
- Set the parameter/config value the expression interpolates, or pass a literal https URL instead of an unresolved reference.
- Ensure the tool is resolved only after the endpoint-producing resource has been provisioned/started (await its endpoint before creating the tool).
- Catch InvalidOperationException during resolution and log which endpoint expression produced an empty value.
Example fix
// before
var tool = builder.AddFoundryToolboxTool("mcp",
ReferenceExpression.Create($"{unconfiguredParam}"));
// after
builder.AddParameter("mcp-endpoint");
var tool = builder.AddFoundryToolboxTool("mcp",
ReferenceExpression.Create($"https://{resource.Resource.Endpoint("https")}")); Defensive patterns
Strategy: validation
Validate before calling
var endpoint = await endpointExpression.GetValueAsync(ct);
if (string.IsNullOrEmpty(endpoint))
throw new InvalidOperationException($"MCP tool '{name}' endpoint resolved to empty value."); Type guard
static bool HasEndpoint(ReferenceExpression e) => !string.IsNullOrWhiteSpace(e.ToString());
Try / catch
try { await definition.ResolveAsync(ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not have a resolvable endpoint URI"))
{ logger.LogWarning(ex, "MCP tool endpoint not resolvable; skipping tool."); } Prevention
- Confirm the referenced resource defines the endpoint the expression interpolates
- Set parameters/config values before building the tool definition
- Resolve tools only after dependent resources are started/provisioned
When it happens
Trigger: The ReferenceExpression passed to FoundryToolboxMcpToolDefinition resolves empty — e.g. it wraps an endpoint resource whose endpoint annotation is unassigned, a parameter with no value set, or a BicepOutputReference/environment variable that is not populated when ResolveAsync runs.
Common situations: Referencing an endpoint of a resource that hasn't started or has no endpoint defined; a config/parameter key missing in appsettings or environment so WithReference-style interpolation yields an empty string; running an AppHost mode where the deployed endpoint output doesn't exist yet.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- A global MCP approval policy cannot be combined with custom…
- An MCP approval filter must specify at least one tool name…
- An MCP approval policy must specify a global mode or at…
- MCP tool ' ' must resolve to a Foundry-reachable absolute…
- MCP tool ' ' cannot both always and never require approval.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/dcbceada99927542.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs:149
}
/// <summary>
/// Gets the MCP endpoint expression for the tool.
/// </summary>
public ReferenceExpression EndpointExpression { get; }
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).
//View on GitHub (pinned to 25830f84bd)