{"record":{"id":"dcbceada99927542","repo":"microsoft/aspire","slug":"mcp-tool-name-does-not-have-a-resolvable-endpoint-uri","errorCode":null,"errorMessage":"MCP tool '{Name}' does not have a resolvable endpoint URI.","messagePattern":"MCP tool '(.+?)' does not have a resolvable endpoint URI\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs","lineNumber":149,"sourceCode":"    }\n\n    /// <summary>\n    /// Gets the MCP endpoint expression for the tool.\n    /// </summary>\n    public ReferenceExpression EndpointExpression { get; }\n\n    public string ServerLabel { get; }\n\n    public string? ServerDescription { get; }\n\n    internal ResolvedFoundryToolboxMcpApprovalPolicy? ApprovalPolicy { get; }\n\n    internal override async ValueTask<ResolvedFoundryToolboxTool> ResolveAsync(CancellationToken cancellationToken)\n    {\n        var endpoint = await EndpointExpression.GetValueAsync(cancellationToken).ConfigureAwait(false);\n        if (string.IsNullOrEmpty(endpoint))\n        {\n            throw new InvalidOperationException(\n                $\"MCP tool '{Name}' does not have a resolvable endpoint URI.\");\n        }\n\n        if (!Uri.TryCreate(endpoint, UriKind.Absolute, out var endpointUri) ||\n            !IsFoundryReachableHttpsEndpoint(endpointUri))\n        {\n            throw new InvalidOperationException(\n                $\"MCP tool '{Name}' must resolve to a Foundry-reachable absolute HTTPS endpoint.\");\n        }\n\n        // Build the OpenAI Responses \"mcp\" tool wire JSON by hand and read it back as a\n        // ProjectsAgentTool. See the comment on FoundryToolboxWebSearchToolDefinition for the\n        // underlying cross-ALC System.ClientModel version mismatch that makes the natural\n        // `ResponseTool.CreateMcpTool(...).AsAgentTool()` round-trip throw in the polyglot\n        // (e.g. JavaScript/TypeScript) AppHostServer host process. Constructing the JSON\n        // ourselves keeps everything inside types that are consistent across the integration's\n        // ALC (BCL + Azure.AI.Projects.Agents + that ALC's copy of System.ClientModel).\n        //","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs#L131-L167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar tool = builder.AddFoundryToolboxTool(\"mcp\",\n    ReferenceExpression.Create($\"{unconfiguredParam}\"));\n// after\nbuilder.AddParameter(\"mcp-endpoint\");\nvar tool = builder.AddFoundryToolboxTool(\"mcp\",\n    ReferenceExpression.Create($\"https://{resource.Resource.Endpoint(\"https\")}\"));","handlingStrategy":"validation","validationCode":"var endpoint = await endpointExpression.GetValueAsync(ct);\nif (string.IsNullOrEmpty(endpoint))\n    throw new InvalidOperationException($\"MCP tool '{name}' endpoint resolved to empty value.\");","typeGuard":"static bool HasEndpoint(ReferenceExpression e) => !string.IsNullOrWhiteSpace(e.ToString());","tryCatchPattern":"try { await definition.ResolveAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not have a resolvable endpoint URI\"))\n{ logger.LogWarning(ex, \"MCP tool endpoint not resolvable; skipping tool.\"); }","preventionTips":["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"],"tags":["foundry","mcp","endpoint-resolution","aspire"],"backgroundTag":"missing-config-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}