microsoft/aspire · error · InvalidOperationException
Existing MCP server configuration
Error message
Existing MCP server configuration '{builder.Resource.Name}' is read-only and cannot create an access policy. What it means
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.
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.
Example fix
// before
var mcp = ns.AddMcpServerConfig("tools", options).AsExisting();
mcp.WithAccessPolicy("api", policyOptions); // throws
// after
var mcp = ns.AddMcpServerConfig("tools", options).AsExisting();
// Configure the access policy on the existing config outside Aspire. Defensive patterns
Strategy: validation
Validate before calling
if (!mcp.Resource.IsExisting)
{
mcp.WithAccessPolicy("api", policyOptions);
} Try / catch
try
{
mcp.WithAccessPolicy("api", policyOptions);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("is read-only"))
{
// manage the policy on the existing MCP config outside Aspire
} Prevention
- 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.
When it happens
Trigger: Calling WithAccessPolicy(name, options) on an AzureConnectorNamespaceMcpServerConfigResource builder whose Resource.IsExisting is true.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- MCP server configuration
- Access policy resource
- An access policy for principal
- Existing connector connection
- Existing MCP server configuration
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/0994855874c49627.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.ConnectorNamespace/AzureConnectorNamespaceExtensions.cs:546
/// <remarks>
/// Managed MCP endpoints reject callers that do not have a config-scoped access policy.
/// Connector Namespace currently supports Microsoft Entra users and groups for these policies.
/// The Azure child resource name is set to the principal object ID as required by the service.
/// </remarks>
/// <ats-returns>The resource builder.</ats-returns>
[AspireExport("withMcpServerConfigAccessPolicy", MethodName = "withAccessPolicy")]
public static IResourceBuilder<AzureConnectorNamespaceMcpServerConfigResource> WithAccessPolicy(
this IResourceBuilder<AzureConnectorNamespaceMcpServerConfigResource> builder,
[ResourceName] string name,
AzureConnectorNamespaceMcpAccessPolicyOptions options)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrWhiteSpace(name);
ArgumentNullException.ThrowIfNull(options);
ValidateMcpAccessPolicyOptions(options);
if (builder.Resource.IsExisting)
{
throw new InvalidOperationException(
$"Existing MCP server configuration '{builder.Resource.Name}' is read-only and cannot create an access policy.");
}
var resourceName = GetValidatedMcpAccessPolicyResourceName(builder.Resource, name, options.ObjectId);
builder.Resource.AccessPolicies.Add(new AzureConnectorNamespaceMcpAccessPolicyResource(
resourceName,
builder.Resource,
options.ObjectId,
options.TenantId,
options.PrincipalType));
return builder;
}
/// <summary>
/// Adds a connector route and an explicit operation allow-list to a managed MCP server configuration.
/// </summary>
/// <param name="builder">The MCP server configuration resource builder.</param>
/// <param name="connectorName">The connector route name.</param>View on GitHub (pinned to 25830f84bd)