Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 28, 2025

Description

Adds two new MCP tools to the CLI that operate independently without requiring a running AppHost:

MCP Tools

  • list_integrations - Lists available Aspire hosting integrations (NuGet packages) from configured package channels, returns structured JSON with Integration schema containing short name, full package ID, and version. Description explains how to add integrations using aspire add <integration-name> and references the get_integration_docs tool for more information.
  • get_integration_docs - Gets documentation URL for a specific integration package. Takes packageId and packageVersion as required parameters and returns content with the NuGet package URL for documentation.

Changes

  • ListIntegrationsTool.cs - Uses IPackagingService to fetch packages, extracts friendly names, uses semantic versioning for correct ordering, returns structured JSON. Updated description to reference get_integration_docs tool.
  • GetIntegrationDocsTool.cs - New tool that returns NuGet package documentation URLs for integrations
  • McpStartCommand.cs - Registers new tools
  • McpCommand.cs - Injects IPackagingService dependency
  • JsonSourceGenerationContext.cs - Added Integration and ListIntegrationsResponse types for AOT-compatible JSON serialization

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?
Original prompt

Add 2 new MCP tools to the CLI that does not talk to the app host.

  • A list_integrations tool that can list the integrations for the apphost
    -A get_aspire_docs tool that returns the content from https://aspire.dev/llms.txt

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Add list_integrations and get_aspire_docs tools to CLI Add list_integrations and get_aspire_docs MCP tools to CLI Nov 28, 2025
Copilot AI requested a review from davidfowl November 28, 2025 07:46
Copilot finished work on behalf of davidfowl November 28, 2025 07:46
@davidfowl
Copy link
Member

@copilot Implement the PR feedback

Copy link
Contributor Author

Copilot AI commented Nov 28, 2025

@copilot Implement the PR feedback

Implemented in 66f7b8b - All feedback has been addressed.

Copilot finished work on behalf of davidfowl November 28, 2025 08:46
Copilot AI requested a review from davidfowl November 28, 2025 08:46
@davidfowl
Copy link
Member

@copilot Why does the schema from the ListIntegrationsTool and GetAspireDocsTool have no properties? For the ListIntegrationsTool we should respond with both names (long and short) and the description should describe how to add integrations to the apphost using the aspire cli.

Copy link
Contributor Author

Copilot AI commented Nov 28, 2025

@copilot Why does the schema from the ListIntegrationsTool and GetAspireDocsTool have no properties? For the ListIntegrationsTool we should respond with both names (long and short) and the description...

Fixed in 2c864f1 - The input schemas now include additionalProperties: false and more descriptive text explaining that no input is required and what the tool returns. The ListIntegrationsTool already returns both the short name (name like "Redis") and the full package ID (packageId like "Aspire.Hosting.Redis"). Updated the description to include aspire add <integration-name> usage instructions.

Copilot finished work on behalf of davidfowl November 28, 2025 08:56
@github-actions
Copy link
Contributor

github-actions bot commented Nov 28, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 13231

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 13231"

@mitchdenny
Copy link
Member

@copilot remove the GetAspireDocsTool from the CLI MCP server. instead I want you to introduce a new annotation called AgentContentAnnotation into the app model (put it in the Aspire.Hosting package.

Introduce an API that looks like this to the app model:

var myresource = builder.AddPostgres("pg")
  .WithAgentContent(async (context) => { });

The idea is that each resource can have a callback which is invoked to get text which can be returned to the agent. Introduce a new MCP tool called get_resource_content which uses the aux backchannel to invoke the callback on the AgentContentAnnotation within the app host.

The context instance will be a new type called AgentContentContext which exposes a model for appending text which is ultimately rendered to the client.

Copy link
Contributor Author

Copilot AI commented Dec 1, 2025

@copilot remove the GetAspireDocsTool from the CLI MCP server. instead I want you to introduce a new annotation called AgentContentAnnotation into the app model (put it in the Aspire.Hosting package...

Implemented in eeaf179:

  • Removed GetAspireDocsTool from the CLI MCP server
  • Added AgentContentAnnotation and AgentContentContext types in Aspire.Hosting.ApplicationModel
  • Added WithAgentContent<T>() extension method on IResourceBuilder<T>
  • Added get_resource_content MCP tool that uses the aux backchannel to invoke the callback
  • Added IServiceProvider to AgentContentContext
  • Marked all new public APIs with [Experimental("ASPIREAGENTCONTENT001")]

Copilot AI changed the title Add list_integrations and get_aspire_docs MCP tools to CLI Add list_integrations and get_resource_content MCP tools to CLI Dec 1, 2025
Copilot AI requested a review from mitchdenny December 1, 2025 04:52
Copilot finished work on behalf of mitchdenny December 1, 2025 04:52
@mitchdenny mitchdenny force-pushed the copilot/add-cli-tools-list-integrations-get-aspire-docs branch from 9ad1588 to 27515a1 Compare December 1, 2025 22:45
@mitchdenny
Copy link
Member

@copilot we have decided to split some of the functionality out of this PR. Make the following changes so we can clean this up and merge it:

  1. Remove the GetResourceDocsTool
  2. Remove the GetResourceDocsAsync call from the backchannel and RPC target in Aspire.Hosting
  3. Remove the AgentContentAnnotation and related extension methods in Aspire.Hosting and Aspire.Hosting.Postgresql

Once those changes are made introduce a new tool called GetIntegrationDocs that runs within the aspire CLI (so not forwarded to the remote MCP endpoint) which returns content like this:

Instructions for the {packageId} integration can be downloaded from:

https://www.nuget.org/packages/{packageId}/{packageVersion}

Review this documentation for instructions on how to use this package within the apphost. Refer to linked documentation for additional information.

The response for the list_resources tool should be updated to refer to the get_integration_docs tool so that the model knows it can request more information on each integration.

Copy link
Contributor Author

Copilot AI commented Dec 4, 2025

@copilot we have decided to split some of the functionality out of this PR. Make the following changes so we can clean this up and merge it:

  1. Remove the GetResourceDocsTool
    ...

Implemented in cc34ed5:

  • Removed GetResourceDocsTool from CLI
  • Removed GetResourceDocsAsync from backchannel RPC target
  • Removed AgentContentAnnotation, AgentContentContext, and WithAgentContent from Aspire.Hosting
  • Removed WithAgentContent usage from PostgresBuilderExtensions
  • Created new GetIntegrationDocsTool that returns NuGet package documentation URLs
  • Updated list_integrations description to reference get_integration_docs tool

Copilot AI changed the title Add list_integrations and get_resource_content MCP tools to CLI Add list_integrations and get_integration_docs MCP tools to CLI Dec 4, 2025
Copilot finished work on behalf of mitchdenny December 4, 2025 22:54
Copilot AI and others added 16 commits December 5, 2025 11:15
@mitchdenny mitchdenny force-pushed the copilot/add-cli-tools-list-integrations-get-aspire-docs branch from cc34ed5 to 244698c Compare December 5, 2025 02:07
@mitchdenny mitchdenny marked this pull request as ready for review December 5, 2025 02:10
Copilot AI review requested due to automatic review settings December 5, 2025 02:10
Copilot finished reviewing on behalf of mitchdenny December 5, 2025 02:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds two new MCP tools to the Aspire CLI that operate independently without requiring a running AppHost. These tools enhance the CLI's capability to provide integration information and documentation to users.

Key Changes:

  • Adds list_integrations tool that retrieves and formats available Aspire hosting integrations from NuGet package channels
  • Adds get_integration_docs tool that returns NuGet documentation URLs for specific integration packages
  • Extends the backchannel monitor interface with SelectedConnection property and GetConnectionsForWorkingDirectory method to support future AppHost selection features

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Aspire.Cli/Mcp/ListIntegrationsTool.cs Implements tool for listing integrations with semantic versioning, deduplication, and friendly name extraction
src/Aspire.Cli/Mcp/GetIntegrationDocsTool.cs Implements tool for retrieving NuGet documentation URLs with input validation
src/Aspire.Cli/JsonSourceGenerationContext.cs Adds AOT-compatible JSON serialization support for Integration and ListIntegrationsResponse types
src/Aspire.Cli/Commands/McpStartCommand.cs Registers new tools and updates tool routing logic to handle non-AppHost tools
src/Aspire.Cli/Commands/McpCommand.cs Injects IPackagingService dependency for MCP command initialization
src/Aspire.Cli/Backchannel/IAuxiliaryBackchannelMonitor.cs Extends interface with SelectedConnection property and GetConnectionsForWorkingDirectory method
src/Aspire.Cli/Backchannel/AuxiliaryBackchannelMonitor.cs Implements new interface members with AppHost selection and scoping logic
tests/Aspire.Cli.Tests/TestServices/TestAuxiliaryBackchannelMonitor.cs Mirrors production implementation for test scenarios
tests/Aspire.Cli.Tests/Mcp/MockPackagingService.cs Provides test doubles for packaging service and NuGet cache
tests/Aspire.Cli.Tests/Mcp/ListIntegrationsToolTests.cs Comprehensive test suite covering various scenarios for ListIntegrationsTool

Comment on lines +12 to +106
internal sealed class GetIntegrationDocsTool : CliMcpTool
{
public override string Name => "get_integration_docs";

public override string Description => "Gets documentation for a specific Aspire hosting integration package. Use this tool to get detailed information about how to use an integration within the AppHost.";

public override JsonElement GetInputSchema()
{
return JsonDocument.Parse("""
{
"type": "object",
"properties": {
"packageId": {
"type": "string",
"description": "The NuGet package ID of the integration (e.g., 'Aspire.Hosting.Redis')."
},
"packageVersion": {
"type": "string",
"description": "The version of the package (e.g., '9.0.0')."
}
},
"required": ["packageId", "packageVersion"],
"additionalProperties": false,
"description": "Gets documentation for a specific Aspire hosting integration. Requires the package ID and version."
}
""").RootElement;
}

public override ValueTask<CallToolResult> CallToolAsync(ModelContextProtocol.Client.McpClient mcpClient, IReadOnlyDictionary<string, JsonElement>? arguments, CancellationToken cancellationToken)
{
// This tool does not use the MCP client as it operates locally
_ = mcpClient;
_ = cancellationToken;

if (arguments == null)
{
return ValueTask.FromResult(new CallToolResult
{
IsError = true,
Content = [new TextContentBlock { Text = "Arguments are required." }]
});
}

if (!arguments.TryGetValue("packageId", out var packageIdElement))
{
return ValueTask.FromResult(new CallToolResult
{
IsError = true,
Content = [new TextContentBlock { Text = "The 'packageId' parameter is required." }]
});
}

var packageId = packageIdElement.GetString();
if (string.IsNullOrEmpty(packageId))
{
return ValueTask.FromResult(new CallToolResult
{
IsError = true,
Content = [new TextContentBlock { Text = "The 'packageId' parameter cannot be empty." }]
});
}

if (!arguments.TryGetValue("packageVersion", out var packageVersionElement))
{
return ValueTask.FromResult(new CallToolResult
{
IsError = true,
Content = [new TextContentBlock { Text = "The 'packageVersion' parameter is required." }]
});
}

var packageVersion = packageVersionElement.GetString();
if (string.IsNullOrEmpty(packageVersion))
{
return ValueTask.FromResult(new CallToolResult
{
IsError = true,
Content = [new TextContentBlock { Text = "The 'packageVersion' parameter cannot be empty." }]
});
}

var content = $"""
Instructions for the {packageId} integration can be downloaded from:
https://www.nuget.org/packages/{packageId}/{packageVersion}
Review this documentation for instructions on how to use this package within the apphost. Refer to linked documentation for additional information.
""";

return ValueTask.FromResult(new CallToolResult
{
Content = [new TextContentBlock { Text = content }]
});
}
}
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test coverage for GetIntegrationDocsTool. While ListIntegrationsTool has comprehensive tests, the GetIntegrationDocsTool lacks any test coverage.

Consider adding tests similar to ListIntegrationsToolTests.cs that verify:

  • Correct tool name and description
  • Valid input schema
  • Error handling when arguments are null or missing
  • Error handling when packageId or packageVersion are empty
  • Successful response with valid parameters
  • Correct URL formatting in the response

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +77
public AppHostConnection? SelectedConnection
{
get
{
var connections = _connections.Values.ToList();

if (connections.Count == 0)
{
return null;
}

// Check if a specific AppHost was selected
if (!string.IsNullOrEmpty(SelectedAppHostPath))
{
var selectedConnection = connections.FirstOrDefault(c =>
c.AppHostInfo?.AppHostPath != null &&
string.Equals(Path.GetFullPath(c.AppHostInfo.AppHostPath), Path.GetFullPath(SelectedAppHostPath), StringComparison.OrdinalIgnoreCase));

if (selectedConnection != null)
{
return selectedConnection;
}

// Clear the selection since the AppHost is no longer available
SelectedAppHostPath = null;
}

// Look for in-scope connections
var inScopeConnections = connections.Where(c => c.IsInScope).ToList();

if (inScopeConnections.Count == 1)
{
return inScopeConnections[0];
}

// Fall back to the first available connection
return connections.FirstOrDefault();
}
}

public IReadOnlyList<AppHostConnection> GetConnectionsForWorkingDirectory(DirectoryInfo workingDirectory)
{
return _connections.Values
.Where(c => IsAppHostInScopeOfDirectory(c.AppHostInfo?.AppHostPath, workingDirectory.FullName))
.ToList();
}

private static bool IsAppHostInScopeOfDirectory(string? appHostPath, string workingDirectory)
{
if (string.IsNullOrEmpty(appHostPath))
{
return false;
}

// Normalize the paths for comparison
var normalizedWorkingDirectory = Path.GetFullPath(workingDirectory);
var normalizedAppHostPath = Path.GetFullPath(appHostPath);

// Check if the AppHost path is within the working directory
var relativePath = Path.GetRelativePath(normalizedWorkingDirectory, normalizedAppHostPath);
return !relativePath.StartsWith("..", StringComparison.Ordinal) && !Path.IsPathRooted(relativePath);
}
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code duplication detected between TestAuxiliaryBackchannelMonitor and AuxiliaryBackchannelMonitor. The SelectedConnection property (lines 16-54) and IsAppHostInScopeOfDirectory method (lines 63-77) are duplicated from the production implementation.

This duplication could lead to maintenance issues if the selection logic needs to be updated. Consider extracting this logic into a shared helper class or extension method that both implementations can use, ensuring the test implementation stays in sync with the production code.

Copilot uses AI. Check for mistakes.
@mitchdenny mitchdenny merged commit 717e670 into main Dec 5, 2025
567 of 571 checks passed
@mitchdenny mitchdenny deleted the copilot/add-cli-tools-list-integrations-get-aspire-docs branch December 5, 2025 03:11
@dotnet-policy-service dotnet-policy-service bot added this to the 13.1 milestone Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants