{"record":{"id":"0994855874c49627","repo":"microsoft/aspire","slug":"existing-mcp-server-configuration-builder-resource-name-is","errorCode":null,"errorMessage":"Existing MCP server configuration '{builder.Resource.Name}' is read-only and cannot create an access policy.","messagePattern":"Existing MCP server configuration '(.+?)' is read-only and cannot create an access policy\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.ConnectorNamespace/AzureConnectorNamespaceExtensions.cs","lineNumber":546,"sourceCode":"    /// <remarks>\n    /// Managed MCP endpoints reject callers that do not have a config-scoped access policy.\n    /// Connector Namespace currently supports Microsoft Entra users and groups for these policies.\n    /// The Azure child resource name is set to the principal object ID as required by the service.\n    /// </remarks>\n    /// <ats-returns>The resource builder.</ats-returns>\n    [AspireExport(\"withMcpServerConfigAccessPolicy\", MethodName = \"withAccessPolicy\")]\n    public static IResourceBuilder<AzureConnectorNamespaceMcpServerConfigResource> WithAccessPolicy(\n        this IResourceBuilder<AzureConnectorNamespaceMcpServerConfigResource> builder,\n        [ResourceName] string name,\n        AzureConnectorNamespaceMcpAccessPolicyOptions options)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrWhiteSpace(name);\n        ArgumentNullException.ThrowIfNull(options);\n        ValidateMcpAccessPolicyOptions(options);\n        if (builder.Resource.IsExisting)\n        {\n            throw new InvalidOperationException(\n                $\"Existing MCP server configuration '{builder.Resource.Name}' is read-only and cannot create an access policy.\");\n        }\n\n        var resourceName = GetValidatedMcpAccessPolicyResourceName(builder.Resource, name, options.ObjectId);\n        builder.Resource.AccessPolicies.Add(new AzureConnectorNamespaceMcpAccessPolicyResource(\n            resourceName,\n            builder.Resource,\n            options.ObjectId,\n            options.TenantId,\n            options.PrincipalType));\n        return builder;\n    }\n\n    /// <summary>\n    /// Adds a connector route and an explicit operation allow-list to a managed MCP server configuration.\n    /// </summary>\n    /// <param name=\"builder\">The MCP server configuration resource builder.</param>\n    /// <param name=\"connectorName\">The connector route name.</param>","sourceCodeStart":528,"sourceCodeEnd":564,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.ConnectorNamespace/AzureConnectorNamespaceExtensions.cs#L528-L564","documentation":"WithAccessPolicy on an MCP server configuration adds an access policy child resource, which is impossible for existing (AsExisting) configurations because Aspire does not own or deploy them. The read-only invariant is enforced at model-build time with InvalidOperationException before any resource is added.","triggerScenarios":"Calling WithAccessPolicy(name, options) on an AzureConnectorNamespaceMcpServerConfigResource builder whose Resource.IsExisting is true.","commonSituations":"Pointing an MCP config at pre-provisioned infrastructure and then trying to grant a client compute resource access via WithAccessPolicy; reusing a modeling extension that assumes create mode.","solutions":["Grant the access policy on the existing MCP server configuration directly in Azure; remove the WithAccessPolicy call.","Model the MCP server configuration as Aspire-created if policies must be code-managed.","Skip WithAccessPolicy conditionally when builder.Resource.IsExisting is true."],"exampleFix":"// before\nvar mcp = ns.AddMcpServerConfig(\"tools\", options).AsExisting();\nmcp.WithAccessPolicy(\"api\", policyOptions); // throws\n\n// after\nvar mcp = ns.AddMcpServerConfig(\"tools\", options).AsExisting();\n// Configure the access policy on the existing config outside Aspire.","handlingStrategy":"validation","validationCode":"if (!mcp.Resource.IsExisting)\n{\n    mcp.WithAccessPolicy(\"api\", policyOptions);\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    mcp.WithAccessPolicy(\"api\", policyOptions);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"is read-only\"))\n{\n    // manage the policy on the existing MCP config outside Aspire\n}","preventionTips":["Treat IsExisting MCP configs as immutable in the Aspire model.","Plan access policies for pre-provisioned infrastructure in your IaC.","Guard shared helper extensions with an IsExisting check."],"tags":["azure","aspire-hosting","mcp","access-policy"],"backgroundTag":"invalid-state-transition","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"}