Skip to content

Commit dc16056

Browse files
committed
Remove diagnostic suppressor
1 parent fe5848d commit dc16056

File tree

6 files changed

+124
-223
lines changed

6 files changed

+124
-223
lines changed

ModelContextProtocol.slnx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,6 @@
7878
<Project Path="tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj" />
7979
<Project Path="tests/ModelContextProtocol.TestServer/ModelContextProtocol.TestServer.csproj" />
8080
<Project Path="tests/ModelContextProtocol.TestSseServer/ModelContextProtocol.TestSseServer.csproj" />
81-
<Project Path="tests/ModelContextProtocol.SuppressorRegressionTest/ModelContextProtocol.SuppressorRegressionTest.csproj" />
81+
<Project Path="tests/ModelContextProtocol.ExperimentalApiRegressionTest/ModelContextProtocol.ExperimentalApiRegressionTest.csproj" />
8282
</Folder>
8383
</Solution>

src/ModelContextProtocol.Analyzers/MCPEXP001Suppressor.cs

Lines changed: 0 additions & 51 deletions
This file was deleted.

tests/ModelContextProtocol.Analyzers.Tests/MCPEXP001SuppressorTests.cs

Lines changed: 0 additions & 159 deletions
This file was deleted.

tests/ModelContextProtocol.SuppressorRegressionTest/ExperimentalPropertyRegressionContext.cs renamed to tests/ModelContextProtocol.ExperimentalApiRegressionTest/ExperimentalPropertyRegressionContext.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
using System.Text.Json.Serialization;
22
using ModelContextProtocol.Protocol;
33

4-
namespace ModelContextProtocol.SuppressorRegressionTest;
4+
namespace ModelContextProtocol.ExperimentalApiRegressionTest;
55

66
/// <summary>
7-
/// This file validates that the MCPEXP001 diagnostic suppressor works correctly.
8-
/// By including MCP protocol types that have experimental properties in a
9-
/// <see cref="JsonSerializerContext"/>, we verify that the source generator does
10-
/// not produce unsuppressed MCPEXP001 diagnostics. If the suppressor is removed
11-
/// or broken, this project will fail to build.
7+
/// This file validates that the System.Text.Json source generator does not produce
8+
/// MCPEXP001 diagnostics for MCP protocol types with experimental properties.
129
/// </summary>
1310
[JsonSerializable(typeof(Tool))]
1411
[JsonSerializable(typeof(ServerCapabilities))]

tests/ModelContextProtocol.SuppressorRegressionTest/ModelContextProtocol.SuppressorRegressionTest.csproj renamed to tests/ModelContextProtocol.ExperimentalApiRegressionTest/ModelContextProtocol.ExperimentalApiRegressionTest.csproj

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
<IsPackable>false</IsPackable>
88

99
<!--
10-
This project validates the MCPEXP001 diagnostic suppressor.
10+
This project validates that MCPEXP001 diagnostics are NOT emitted by the
11+
System.Text.Json source generator for types with experimental properties.
1112
tests/Directory.Build.props suppresses MCPEXP001 globally for all test projects,
1213
but this project must NOT suppress it: its successful compilation IS the test.
13-
If the suppressor breaks, this project will fail to build with MCPEXP001 errors
14-
from the source-generated code that references experimental types.
1514
-->
1615
<NoWarn>$(NoWarn.Replace('MCPEXP001',''))</NoWarn>
1716

@@ -25,9 +24,6 @@
2524

2625
<ItemGroup>
2726
<ProjectReference Include="..\..\src\ModelContextProtocol.Core\ModelContextProtocol.Core.csproj" />
28-
<ProjectReference Include="..\..\src\ModelContextProtocol.Analyzers\ModelContextProtocol.Analyzers.csproj"
29-
OutputItemType="Analyzer"
30-
ReferenceOutputAssembly="false" />
3127
</ItemGroup>
3228

3329
</Project>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
using ModelContextProtocol.Protocol;
4+
5+
namespace ModelContextProtocol.Tests;
6+
7+
/// <summary>
8+
/// Validates that the internal property pattern used for experimental properties
9+
/// produces the expected serialization behavior for SDK consumers using source generators.
10+
/// </summary>
11+
/// <remarks>
12+
/// <para>
13+
/// Experimental properties (e.g. <see cref="Tool.Execution"/>, <see cref="ServerCapabilities.Tasks"/>)
14+
/// use an internal <c>*Core</c> property for serialization. A consumer's source-generated
15+
/// <see cref="JsonSerializerContext"/> cannot see internal members, so experimental data is
16+
/// silently dropped unless the consumer chains the SDK's resolver into their options.
17+
/// </para>
18+
/// <para>
19+
/// These tests depend on <see cref="Tool.Execution"/> and <see cref="ServerCapabilities.Tasks"/>
20+
/// being experimental. When those APIs stabilize, update these tests to reference whatever
21+
/// experimental properties exist at that time, or remove them entirely if no experimental
22+
/// APIs remain.
23+
/// </para>
24+
/// </remarks>
25+
public class ExperimentalPropertySerializationTests
26+
{
27+
[Fact]
28+
public void ExperimentalProperties_Dropped_WithConsumerContextOnly()
29+
{
30+
var options = new JsonSerializerOptions
31+
{
32+
TypeInfoResolverChain = { ConsumerJsonContext.Default }
33+
};
34+
35+
var tool = new Tool
36+
{
37+
Name = "test-tool",
38+
Execution = new ToolExecution { TaskSupport = ToolTaskSupport.Optional }
39+
};
40+
41+
string json = JsonSerializer.Serialize(tool, options);
42+
Assert.DoesNotContain("\"execution\"", json);
43+
Assert.Contains("\"name\"", json);
44+
}
45+
46+
[Fact]
47+
public void ExperimentalProperties_IgnoredOnDeserialize_WithConsumerContextOnly()
48+
{
49+
string json = JsonSerializer.Serialize(
50+
new Tool
51+
{
52+
Name = "test-tool",
53+
Execution = new ToolExecution { TaskSupport = ToolTaskSupport.Optional }
54+
},
55+
McpJsonUtilities.DefaultOptions);
56+
Assert.Contains("\"execution\"", json);
57+
58+
var options = new JsonSerializerOptions
59+
{
60+
TypeInfoResolverChain = { ConsumerJsonContext.Default }
61+
};
62+
var deserialized = JsonSerializer.Deserialize<Tool>(json, options)!;
63+
Assert.Equal("test-tool", deserialized.Name);
64+
Assert.Null(deserialized.Execution);
65+
}
66+
67+
[Fact]
68+
public void ExperimentalProperties_RoundTrip_WhenSdkResolverIsChained()
69+
{
70+
var options = new JsonSerializerOptions
71+
{
72+
TypeInfoResolverChain =
73+
{
74+
McpJsonUtilities.DefaultOptions.TypeInfoResolver!,
75+
ConsumerJsonContext.Default,
76+
}
77+
};
78+
79+
var tool = new Tool
80+
{
81+
Name = "test-tool",
82+
Execution = new ToolExecution { TaskSupport = ToolTaskSupport.Optional }
83+
};
84+
85+
string json = JsonSerializer.Serialize(tool, options);
86+
Assert.Contains("\"execution\"", json);
87+
Assert.Contains("\"name\"", json);
88+
89+
var deserialized = JsonSerializer.Deserialize<Tool>(json, options)!;
90+
Assert.Equal("test-tool", deserialized.Name);
91+
Assert.NotNull(deserialized.Execution);
92+
Assert.Equal(ToolTaskSupport.Optional, deserialized.Execution.TaskSupport);
93+
}
94+
95+
[Fact]
96+
public void ExperimentalProperties_RoundTrip_WithDefaultOptions()
97+
{
98+
var capabilities = new ServerCapabilities
99+
{
100+
Tasks = new McpTasksCapability()
101+
};
102+
103+
string json = JsonSerializer.Serialize(capabilities, McpJsonUtilities.DefaultOptions);
104+
Assert.Contains("\"tasks\"", json);
105+
106+
var deserialized = JsonSerializer.Deserialize<ServerCapabilities>(json, McpJsonUtilities.DefaultOptions)!;
107+
Assert.NotNull(deserialized.Tasks);
108+
}
109+
}
110+
111+
[JsonSerializable(typeof(Tool))]
112+
[JsonSerializable(typeof(ServerCapabilities))]
113+
[JsonSerializable(typeof(ClientCapabilities))]
114+
[JsonSerializable(typeof(CallToolResult))]
115+
[JsonSerializable(typeof(CallToolRequestParams))]
116+
[JsonSerializable(typeof(CreateMessageRequestParams))]
117+
[JsonSerializable(typeof(ElicitRequestParams))]
118+
internal partial class ConsumerJsonContext : JsonSerializerContext;

0 commit comments

Comments
 (0)