{"record":{"id":"8ef8f73bf45f1f7f","repo":"microsoft/aspire","slug":"mcp-tool-name-must-resolve-to-a-foundry-reachable-absolute","errorCode":null,"errorMessage":"MCP tool '{Name}' must resolve to a Foundry-reachable absolute HTTPS endpoint.","messagePattern":"MCP tool '(.+?)' must resolve to a Foundry-reachable absolute HTTPS endpoint\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs","lineNumber":156,"sourceCode":"    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        //\n        // OpenAI Responses \"mcp\" tool wire shape:\n        //   {\n        //     \"type\": \"mcp\",\n        //     \"server_label\": \"<required>\",\n        //     \"server_url\":   \"<absolute uri>\" // required for hosted MCP\n        //   }\n        // See https://platform.openai.com/docs/api-reference/responses/create#responses-create-tools","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxToolDefinition.cs#L138-L174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Deploy or host the MCP server at a publicly reachable HTTPS URL and use that as the endpoint.","Change the scheme to https and remove any user info from the URL.","Verify the string is a full absolute URI (e.g. https://host/mcp), not a relative path or bare hostname.","For local testing, use a tunnel (dev tunnels/ngrok) that exposes a public HTTPS URL."],"exampleFix":"// before\nReferenceExpression.Create($\"http://localhost:8080/mcp\")\n// after\nReferenceExpression.Create($\"https://my-mcp.example.com/mcp\")","handlingStrategy":"validation","validationCode":"if (Uri.TryCreate(endpoint, UriKind.Absolute, out var uri)\n    && uri.Scheme == Uri.UriSchemeHttps\n    && string.IsNullOrEmpty(uri.UserInfo)\n    && !uri.IsLoopback\n    && !uri.Host.EndsWith(\"localhost\", StringComparison.OrdinalIgnoreCase))\n{ /* endpoint is Foundry-reachable */ }","typeGuard":"static bool IsFoundryReachable(Uri u) =>\n    u.Scheme == Uri.UriSchemeHttps && string.IsNullOrEmpty(u.UserInfo) &&\n    !u.IsLoopback && !u.Host.TrimEnd('.').EndsWith(\"localhost\", StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try { await definition.ResolveAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Foundry-reachable absolute HTTPS endpoint\"))\n{ logger.LogError(\"Endpoint '{Endpoint}' must be a public absolute HTTPS URL.\", endpoint); }","preventionTips":["Always use https:// and full absolute URLs for MCP servers","Never point Foundry tools at localhost — use a public tunnel for local dev","Strip credentials from URLs; Foundry does not accept user info in the endpoint"],"tags":["foundry","mcp","https","url-validation","aspire"],"backgroundTag":"invalid-url-format","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"}