Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 17, 2025

  • Investigate the CS1066 warning issue
  • Identify the root cause
  • Implement a fix (DiagnosticSuppressor)
  • Add tests for the fix
  • Validate the fix works
  • Address code review feedback
  • Run CodeQL security check (no issues found)
  • Verify full SDK build succeeds
  • Factor out attribute name constants into shared McpAttributeNames class
  • Match on symbol rather than by name using SymbolEqualityComparer
  • Update existing generator tests to validate no unexpected diagnostics are emitted

Summary

This PR adds a DiagnosticSuppressor that suppresses CS1066 compiler warnings for MCP server methods (tools, prompts, resources) that have optional parameters with default values.

Problem

When users define MCP tool methods as partial methods with optional parameters:

[McpServerTool]
public partial string Hello(string name, bool loud = false)  // CS1066 warning here
{
    return name;
}

The XmlToDescriptionGenerator creates a defining declaration (no body) with the same defaults. The compiler then warns with CS1066 that the defaults on the user's implementing declaration are redundant. This creates noisy CI logs with many warnings.

Solution

Added a DiagnosticSuppressor (CS1066Suppressor.cs) that:

  • Detects CS1066 warnings on parameters
  • Checks if the containing method has [McpServerTool], [McpServerPrompt], or [McpServerResource] attributes using symbol comparison
  • Suppresses the warning if an MCP attribute is found
  • Caches semantic models and attribute symbols per compilation for performance

Also added McpAttributeNames.cs to share attribute name constants between the generator and suppressor.

Tests

Updated the existing XmlToDescriptionGeneratorTests.RunGenerator method to:

  • Accept expected diagnostic IDs as parameters
  • Fail tests if any unexpected diagnostics (of any verbosity level) are emitted
  • Properly run the CS1066Suppressor alongside the generator

Updated 8 tests that expect specific diagnostics (MCP001, MCP002) to pass those diagnostic IDs as expected.

Added 5 new tests in CS1066SuppressorTests.cs:

  • Suppressor_WithMcpServerToolAttribute_SuppressesCS1066
  • Suppressor_WithMcpServerPromptAttribute_SuppressesCS1066
  • Suppressor_WithMcpServerResourceAttribute_SuppressesCS1066
  • Suppressor_WithoutMcpAttribute_DoesNotSuppressCS1066
  • Suppressor_WithMultipleParameters_SuppressesAllCS1066

All 48 analyzer tests pass.

Original prompt

This section details on the original issue you should resolve

<issue_title>CS1066 warnings for MCP tool methods with optional parameters</issue_title>
<issue_description>Describe the bug
When the ModelContextProtocol C# SDK’s XML Documentation Source Generator runs against an assembly that defines MCP tools with optional parameters (defaults like bool forceReload = false, string? framework = null, etc.), the build produces many CS1066 warnings.

Example warning shape:

warning CS1066: The default value specified for parameter 'forceReload' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments

This appears to be caused by how the XML documentation source generator (and/or the generated tool registration/invocation code it participates in) references the tool methods—likely in a context where optional-argument semantics do not apply (e.g., method group conversion to a delegate or other generated call sites). The result is that optional defaults, which are intentional and useful for tool ergonomics and MCP metadata/schema, are flagged as “having no effect,” and the warnings repeat across many tool methods, creating very noisy CI logs.

To Reproduce
Steps to reproduce the behavior:

  1. Create a minimal .NET console app (net8.0 or net10.0).
  2. Add the MCP server SDK package (observed with 0.5.0-preview.1).
  3. Define an [McpServerToolType] class with [McpServerTool] methods that include optional parameters with default values.
  4. Register tools using WithToolsFromAssembly() (or an equivalent SDK mechanism that triggers tool registration / source generation).
  5. Build the project.

Minimal code sample:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = Host.CreateApplicationBuilder(args);

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();

await builder.Build().RunAsync();

[McpServerToolType]
public sealed class SampleTools
{
    [McpServerTool, Description("Example tool with optional params")]
    public string Hello(
        [Description("Name to greet")] string name,
        [Description("Optional loud flag")] bool loud = false,
        [Description("Optional prefix")] string prefix = "Hello")
        => loud ? $"{prefix.ToUpperInvariant()} {name}!" : $"{prefix} {name}";
}

Expected behavior
The SDK’s normal tool registration pattern should not produce CS1066 warnings for MCP tool methods that declare optional parameters with defaults.

Optional parameters are a common ergonomic pattern for tool methods and are useful for schema/metadata and for runtime argument binding behavior. Downstream projects shouldn’t need to suppress CS1066 globally to get clean CI builds.

Logs
Representative warning (actual projects may emit hundreds of these):
warning CS1066: The default value specified for parameter 'loud' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments

Observed in CI/CD during dotnet build -c Release on GitHub Actions (Ubuntu runner) and locally on Windows.

Additional context
This appears to be caused by how the SDK (likely via source generator output) binds tool methods into the runtime invocation pipeline. CS1066 is typically emitted when a method with optional parameter defaults is “used” in a context where optional arguments cannot be applied (e.g., method group conversion to a delegate with a fixed signature or a generated call site that always supplies explicit arguments).

Recommendation / likely fix direction:

  • Adjust the generated tool registration/invocation code so it does not reference the original tool method in a way that disables optional-argument semantics.
  • Prefer generating a wrapper invoker per tool that:
    • takes a structured argument payload (e.g., JsonElement / dictionary),
    • fills missing arguments using reflection (ParameterInfo.HasDefaultValue / DefaultValue) or equivalent logic,
    • and then invokes the tool method without producing CS1066.
  • Register the wrapper invoker as the tool entrypoint, rather than binding directly to the original method group.

Workaround today: downstream projects can suppress CS1066, but that’s a blunt workaround and not ideal for libraries/templates.</issue_description>

<agent_instructions>Ignore everything in the issue other than the cited problem and repro. Validate that you're able to reproduce the problem, and then assuming you can, please fix it. </agent_instructions>

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


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits December 17, 2025 20:32
Add a DiagnosticSuppressor that suppresses CS1066 warnings for methods
marked with [McpServerTool], [McpServerPrompt], or [McpServerResource]
attributes. This allows users to specify default parameter values in
their implementing declarations without compiler warnings.

The XmlToDescriptionGenerator already copies these defaults to the
generated defining declaration, making them functional for callers
and reflection.

Co-authored-by: stephentoub <[email protected]>
- Add semantic model caching per syntax tree to avoid redundant calls
- Remove unnecessary try-catch block in test helper
- Fix test assertions to use correct diagnostic checking pattern

Co-authored-by: stephentoub <[email protected]>
Copilot AI changed the title [WIP] Fix CS1066 warnings for MCP tool methods with optional parameters Add CS1066 suppressor for MCP server methods with optional parameters Dec 17, 2025
Copilot AI requested a review from stephentoub December 17, 2025 20:51
Copy link
Contributor

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

[Fact]
public void Suppressor_WithMcpServerToolAttribute_SuppressesCS1066()
{
var result = RunSuppressor("""
Copy link
Contributor

Choose a reason for hiding this comment

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

Why weren't any of the existing tests failing with cs1066 diagnostics? Are they missing something that will fail if other diagnostics show up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The existing tests don't fail because they only check for error-level diagnostics in the Success property (line 1764: !diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)). CS1066 is a warning, not an error, so it doesn't affect test success. The tests also don't explicitly assert that no warnings are present.

Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot, please fix them to validate that no warning or error diagnostics store up

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in db0ba50. Updated XmlToDescriptionGeneratorTests.RunGenerator to run the CS1066Suppressor alongside the generator and check for unsuppressed CS1066 warnings. Tests will now fail if any CS1066 warnings are not properly suppressed.

Copy link
Contributor

@stephentoub stephentoub Dec 18, 2025

Choose a reason for hiding this comment

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

Tests will now fail if any CS1066 warnings are not properly suppressed.

@copilot, I want the tests to fail if any warning or error is issued. Actually, just make it so that any unexpected diagnostic, regardless of verbosity, fails the tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

@stephentoub stephentoub marked this pull request as ready for review December 17, 2025 22:29
…symbol

- Extract shared McpAttributeNames class with constants used by both
  XmlToDescriptionGenerator and CS1066Suppressor
- Update CS1066Suppressor to match attributes using SymbolEqualityComparer
  instead of string comparison
- Cache attribute symbols per compilation for efficiency

Co-authored-by: stephentoub <[email protected]>
Update XmlToDescriptionGeneratorTests.RunGenerator to:
- Run the CS1066Suppressor alongside the generator
- Check for unsuppressed CS1066 warnings in addition to generator errors
- Fail tests if any CS1066 warnings are not properly suppressed

This ensures the generator tests will fail if the suppressor doesn't
properly handle CS1066 warnings for partial methods with default
parameter values.

Co-authored-by: stephentoub <[email protected]>
- Run CS1066Suppressor alongside the generator in tests
- Check for unsuppressed CS1066 warnings and fail tests if any are found
- Generator errors cause test failures
- Generator warnings are allowed (some tests like MCP001 invalid XML expect warnings)

Co-authored-by: stephentoub <[email protected]>
@stephentoub
Copy link
Contributor

@copilot, please update all of the source generator tests to validate that no unexpected diagnostics of any verbosity level are emitted.

- Changed RunGenerator to accept expected diagnostic IDs as parameters
- Tests now fail if any unexpected diagnostics (of any verbosity) are emitted
- Updated 8 tests that expect specific diagnostics (MCP001, MCP002) to pass
  those diagnostic IDs as expected
- All 48 analyzer tests pass

Co-authored-by: stephentoub <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 18, 2025

@copilot, please update all of the source generator tests to validate that no unexpected diagnostics of any verbosity level are emitted.

Done in f811455. Updated RunGenerator to accept expected diagnostic IDs as parameters. Tests now fail if any unexpected diagnostics (of any verbosity level) are emitted. Updated 8 tests that expect specific diagnostics (MCP001, MCP002) to pass those diagnostic IDs as expected.

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.

CS1066 warnings for MCP tool methods with optional parameters

3 participants