Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
416e1b9
Initial plan
Copilot Oct 19, 2025
031a51a
Add source generator project and initial implementation
Copilot Oct 19, 2025
721ce02
Complete source generator implementation with README and fix analyzer…
Copilot Oct 19, 2025
0424b0c
Add example documentation and update README with availability info
Copilot Oct 19, 2025
4f96860
Convert to incremental generator, add parameter/return docs support, …
Copilot Oct 20, 2025
5ade3c3
Apply ASP.NET Core OpenAPI generator patterns: struct for caching, ca…
Copilot Oct 20, 2025
c7898da
Add tests for ASP.NET Core OpenAPI generator improvements: string esc…
Copilot Oct 20, 2025
3cf7601
Address all review feedback: single file generation, nullable disable…
Copilot Oct 20, 2025
a7e54c7
Fix nested type indentation calculation
Copilot Oct 20, 2025
a5b8d2b
Address final review feedback: simplify attribute checks, use newline…
Copilot Oct 20, 2025
e04d9dd
Fix CI build failures by removing direct Analyzer reference that expe…
Copilot Oct 20, 2025
fe179cf
Remove Benefits section from README per review feedback
Copilot Oct 20, 2025
efc0626
Merge branch 'main' into copilot/scaffold-analyzer-source-generator
stephentoub Oct 23, 2025
288e1fe
Fix CI build failures by disabling parallel builds for Core project t…
Copilot Oct 25, 2025
7376e58
Fix packaging path for analyzer DLL - remove incorrect $(Configuratio…
Copilot Oct 25, 2025
4c01569
Fix analyzer packaging - use $(Configuration) in path as SourceGenera…
Copilot Oct 25, 2025
c337fd2
Fix analyzer reference and packaging - use SetTargetFramework to ensu…
Copilot Oct 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
<!-- Build Infra & Packaging -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />

<!-- Source Generator & Analyzer dependencies -->
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />

<!-- Testing dependencies -->
<PackageVersion Include="Anthropic.SDK" Version="5.6.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.4">
Expand Down
2 changes: 2 additions & 0 deletions ModelContextProtocol.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@
<File Path="src/Directory.Build.props" />
<Project Path="src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj" />
<Project Path="src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj" />
<Project Path="src/ModelContextProtocol.SourceGenerators/ModelContextProtocol.SourceGenerators.csproj" />
<Project Path="src/ModelContextProtocol/ModelContextProtocol.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj" />
<Project Path="tests/ModelContextProtocol.SourceGenerators.Tests/ModelContextProtocol.SourceGenerators.Tests.csproj" />
<Project Path="tests/ModelContextProtocol.TestOAuthServer/ModelContextProtocol.TestOAuthServer.csproj" />
<Project Path="tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj" />
<Project Path="tests/ModelContextProtocol.TestServer/ModelContextProtocol.TestServer.csproj" />
Expand Down
19 changes: 19 additions & 0 deletions src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<Description>Core .NET SDK for the Model Context Protocol (MCP)</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<!-- Disable parallel builds to avoid analyzer locking issues during multi-targeted builds -->
<BuildInParallel>false</BuildInParallel>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
Expand Down Expand Up @@ -47,4 +49,21 @@
<None Include="README.md" pack="true" PackagePath="\" />
</ItemGroup>

<!-- Include source generator as an analyzer -->
<ItemGroup>
<ProjectReference Include="..\ModelContextProtocol.SourceGenerators\ModelContextProtocol.SourceGenerators.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
SetTargetFramework="TargetFramework=netstandard2.0" />
</ItemGroup>

<!-- Package the analyzer DLL into the NuGet package -->
<!-- When using SetTargetFramework, the SourceGenerators outputs to bin/netstandard2.0 without the Configuration folder -->
<ItemGroup>
<None Include="$(ArtifactsDir)bin\ModelContextProtocol.SourceGenerators\netstandard2.0\ModelContextProtocol.SourceGenerators.dll"
Pack="true"
PackagePath="analyzers/dotnet/cs"
Visible="false" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
<IsPackable>false</IsPackable>
<IncludeBuildOutput>false</IncludeBuildOutput>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>

<!-- Remove auto-included polyfills from Directory.Build.props -->
<ItemGroup>
<Compile Remove="..\Common\Polyfills\**\*.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
</ItemGroup>

</Project>
97 changes: 97 additions & 0 deletions src/ModelContextProtocol.SourceGenerators/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# ModelContextProtocol.SourceGenerators

This project contains source generators for the Model Context Protocol C# SDK.

## XmlToDescriptionGenerator

This source generator automatically creates `Description` attributes from XML documentation comments for partial methods tagged with `[McpServerTool]`.

### How it works

When you write a partial method with:
1. An `[McpServerTool]` attribute
2. XML documentation comments (specifically a `<summary>` tag)
3. NO existing `[Description]` attribute

The generator will create a partial method declaration with a `[Description]` attribute containing the text from the XML `<summary>` element.

### Example Usage

**Your code:**
```csharp
using ModelContextProtocol.Server;
using System.ComponentModel;

[McpServerToolType]
public partial class MyTools
{
/// <summary>
/// This tool echoes the input message back to the user.
/// </summary>
/// <param name="message">The message to echo</param>
/// <returns>The echoed message</returns>
[McpServerTool]
public static partial string Echo(string message)
{
return $"Echo: {message}";
}
}
```

**Generated code:**
```csharp
// <auto-generated/>
#nullable disable

using System.ComponentModel;
using ModelContextProtocol.Server;

namespace YourNamespace
{
public partial class MyTools
{
[Description("This tool echoes the input message back to the user.")]
[return: Description("The echoed message")]
public static partial string Echo([Description("The message to echo")] string message);
}
}
```

### Requirements

- Your method must be marked as `partial`
- Your method must have the `[McpServerTool]`, `[McpServerPrompt]`, or `[McpServerResource]` attribute
- Your method must have XML documentation comments (e.g., `<summary>`, `<param>`, or `<returns>` tags)
- Your project must reference `ModelContextProtocol.Core` directly (the source generator is distributed with this package)

The generator will only add `[Description]` attributes for elements that don't already have them.

### Availability

The source generator is distributed as part of the `ModelContextProtocol.Core` NuGet package and will be automatically available when you reference that package in your project.

### Advanced Features

The generator intelligently fills in missing Description attributes:

- **Method Description**: Combines `<summary>` and `<remarks>` XML elements
- **Parameter Descriptions**: Extracts from `<param>` XML elements (only for parameters without existing Description attributes)
- **Return Description**: Extracts from `<returns>` XML element (only if not already present)

The generator only generates attributes that are missing, so you can mix XML documentation with explicit Description attributes as needed.

### Implementation Details

- **Incremental Generator**: Uses `IIncrementalGenerator` for optimal build performance
- **Symbol-based Detection**: Compares attribute symbols using `SymbolEqualityComparer` for reliability
- **Efficient Filtering**: Syntax-only predicate filters candidates before expensive semantic analysis
- **Cancellation Support**: Respects cancellation tokens throughout generation pipeline
- **String Escaping**: Properly escapes special characters (quotes, backslashes, newlines, tabs)
- **Error Handling**: Gracefully handles invalid XML in documentation comments

### Notes

- Multi-line XML comments are combined into single-line descriptions
- Only partial methods with implementations (method bodies) are supported
- Generic types are handled with proper arity in generated file names
- All generated code is marked with `<auto-generated/>` and `#nullable enable`
Loading
Loading