microsoft/aspire · error · McpProtocolException

InternalError

InternalError

Error message

No Aspire AppHost is currently running. To use resource MCP tools, start an Aspire application (e.g. 'aspire run') and then retry.

What it means

Resource MCP tools are proxied through the AppHost auxiliary backchannel. When HandleCallToolAsync resolves a resource tool but GetSelectedConnectionAsync returns no active AppHost connection, the CLI throws McpProtocolException with InternalError explaining that no Aspire AppHost is running.

Solutions

  1. Start an Aspire AppHost with 'aspire run' and retry the tool call
  2. Verify the AppHost is still running and its backchannel is alive; restart it if it exited
  3. Call 'refresh_tools' after the AppHost starts so the client picks up the now-available tools

Example fix

// before
var resources = await mcpClient.CallToolAsync("list_resources");
// after
if (!await IsAppHostRunningAsync())
{
    Console.Error.WriteLine("Start the AppHost with 'aspire run' first.");
    return;
}
var resources = await mcpClient.CallToolAsync("list_resources");
Defensive patterns

Strategy: retry

Validate before calling

// check for a live run/backchannel before calling resource tools
var conns = await backchannelMonitor.GetCurrentConnectionsAsync();
if (conns.Count == 0) { Console.Error.WriteLine("Start the AppHost with 'aspire run' first."); return; }

Type guard

bool hasAppHost = connections.Count > 0;

Try / catch

try
{
    result = await client.CallToolAsync(toolName, args);
}
catch (McpProtocolException ex) when (ex.Message.Contains("No Aspire AppHost is currently running"))
{
    await StartAppHostAsync();
    result = await client.CallToolAsync(toolName, args); // retry after starting
}

Prevention

When it happens

Trigger: Calling any resource MCP tool (mapped in resourceToolMap) while no AppHost is connected — the selection step found zero candidate backchannel connections (no 'aspire run' session, AppHost stopped/crashed, or backchannel not established).

Common situations: Agent invokes resource tools before 'aspire run' was started; the AppHost exited or was terminated mid-session; CLI was launched in a directory/session without a live run.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/64c1b3f09aa17df8. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Commands/AgentMcpCommand.cs:265

        // Refresh resource tools if needed (e.g., AppHost selection changed or invalidated)
        if (!_resourceToolRefreshService.TryGetResourceToolMap(out var resourceToolMap))
        {
            bool changed;
            (resourceToolMap, changed) = await _resourceToolRefreshService.RefreshResourceToolMapAsync(cancellationToken);
            if (changed)
            {
                await _resourceToolRefreshService.SendToolsListChangedNotificationAsync(cancellationToken).ConfigureAwait(false);
            }
            toolsRefreshed = true;
        }

        // Resource MCP tools are invoked via the AppHost backchannel (AppHost proxies to the resource MCP endpoint).
        if (resourceToolMap.TryGetValue(toolName, out var resourceAndTool))
        {
            var connection = await GetSelectedConnectionAsync(cancellationToken).ConfigureAwait(false);
            if (connection == null)
            {
                throw new McpProtocolException(
                    "No Aspire AppHost is currently running. To use resource MCP tools, start an Aspire application (e.g. 'aspire run') and then retry.",
                    McpErrorCode.InternalError);
            }

            var args = request.Params?.Arguments is { } a
                ? new Dictionary<string, JsonElement>(a)
                : null;

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Invoking tool {Name} with arguments {Arguments}", toolName, JsonSerializer.Serialize(args, BackchannelJsonSerializerContext.Default.DictionaryStringJsonElement));
            }

            var result = await connection.CallResourceMcpToolAsync(resourceAndTool.ResourceName, resourceAndTool.Tool.Name, args, cancellationToken).ConfigureAwait(false);

            if (result is null)
            {
                throw new McpProtocolException($"Failed to get MCP tool result for '{toolName}'. Try refreshing the tools with 'refresh_tools'.", McpErrorCode.InternalError);

View on GitHub (pinned to 25830f84bd)