Skip to content

Fix enum serialization #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 1 addition & 17 deletions src/ModelContextProtocol/Client/McpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, C
Throw.IfNull(client);

return client.SendRequestAsync<EmptyResult>(
CreateRequest("logging/setLevel", new() { ["level"] = level.ToJsonValue() }),
CreateRequest("logging/setLevel", new() { ["level"] = level }),
cancellationToken);
}

Expand Down Expand Up @@ -514,22 +514,6 @@ private static JsonRpcRequest CreateRequest(string method, Dictionary<string, ob
return parameters;
}

private static string ToJsonValue(this LoggingLevel level)
{
return level switch
{
LoggingLevel.Debug => "debug",
LoggingLevel.Info => "info",
LoggingLevel.Notice => "notice",
LoggingLevel.Warning => "warning",
LoggingLevel.Error => "error",
LoggingLevel.Critical => "critical",
LoggingLevel.Alert => "alert",
LoggingLevel.Emergency => "emergency",
_ => throw new ArgumentOutOfRangeException(nameof(level))
};
}

/// <summary>Provides an AI function that calls a tool through <see cref="IMcpClient"/>.</summary>
private sealed class McpAIFunction(IMcpClient client, Tool tool) : AIFunction
{
Expand Down
8 changes: 7 additions & 1 deletion src/ModelContextProtocol/Protocol/Types/ContextInclusion.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
namespace ModelContextProtocol.Protocol.Types;
using System.Text.Json.Serialization;

namespace ModelContextProtocol.Protocol.Types;

/// <summary>
/// A request to include context from one or more MCP servers (including the caller), to be attached to the prompt.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter<ContextInclusion>))]
public enum ContextInclusion
{
/// <summary>
/// No context should be included.
/// </summary>
[JsonStringEnumMemberName("none")]
None,

/// <summary>
/// Include context from the server that sent the request.
/// </summary>
[JsonStringEnumMemberName("thisServer")]
ThisServer,

/// <summary>
/// Include context from all servers that the client is connected to.
/// </summary>
[JsonStringEnumMemberName("allServers")]
AllServers
}
17 changes: 9 additions & 8 deletions src/ModelContextProtocol/Protocol/Types/LoggingLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,38 @@ namespace ModelContextProtocol.Protocol.Types;
/// These map to syslog message severities, as specified in RFC-5424:
/// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter<LoggingLevel>))]
public enum LoggingLevel
{
/// <summary>Detailed debug information, typically only valuable to developers.</summary>
[JsonPropertyName("debug")]
[JsonStringEnumMemberName("debug")]
Debug,

/// <summary>Normal operational messages that require no action.</summary>
[JsonPropertyName("info")]
[JsonStringEnumMemberName("info")]
Info,

/// <summary>Normal but significant events that might deserve attention.</summary>
[JsonPropertyName("notice")]
[JsonStringEnumMemberName("notice")]
Notice,

/// <summary>Warning conditions that don't represent an error but indicate potential issues.</summary>
[JsonPropertyName("warning")]
[JsonStringEnumMemberName("warning")]
Warning,

/// <summary>Error conditions that should be addressed but don't require immediate action.</summary>
[JsonPropertyName("error")]
[JsonStringEnumMemberName("error")]
Error,

/// <summary>Critical conditions that require immediate attention.</summary>
[JsonPropertyName("critical")]
[JsonStringEnumMemberName("critical")]
Critical,

/// <summary>Action must be taken immediately to address the condition.</summary>
[JsonPropertyName("alert")]
[JsonStringEnumMemberName("alert")]
Alert,

/// <summary>System is unusable and requires immediate attention.</summary>
[JsonPropertyName("emergency")]
[JsonStringEnumMemberName("emergency")]
Emergency
}
5 changes: 3 additions & 2 deletions src/ModelContextProtocol/Protocol/Types/Role.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ namespace ModelContextProtocol.Protocol.Types;
/// Represents the type of role in the conversation.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter<Role>))]
public enum Role
{
/// <summary>
/// Corresponds to the user in the conversation.
/// </summary>
[JsonPropertyName("user")]
[JsonStringEnumMemberName("user")]
User,

/// <summary>
/// Corresponds to the AI in the conversation.
/// </summary>
[JsonPropertyName("assistant")]
[JsonStringEnumMemberName("assistant")]
Assistant
}
38 changes: 38 additions & 0 deletions tests/ModelContextProtocol.Tests/Protocol/ProtocolTypeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ModelContextProtocol.Protocol.Types;
using ModelContextProtocol.Utils.Json;
using System.Text.Json;

namespace ModelContextProtocol.Tests.Protocol;
Expand Down Expand Up @@ -51,4 +52,41 @@ public static void ToolInputSchema_AcceptsValidSchemaDocuments(string validSchem

Assert.True(JsonElement.DeepEquals(document.RootElement, tool.InputSchema));
}

[Theory]
[InlineData(Role.User, "\"user\"")]
[InlineData(Role.Assistant, "\"assistant\"")]
public static void SerializeRole_ShouldBeCamelCased(Role role, string expectedValue)
{
var actualValue = JsonSerializer.Serialize(role);

Assert.Equal(expectedValue, actualValue);
}

[Theory]
[InlineData(LoggingLevel.Debug, "\"debug\"")]
[InlineData(LoggingLevel.Info, "\"info\"")]
[InlineData(LoggingLevel.Notice, "\"notice\"")]
[InlineData(LoggingLevel.Warning, "\"warning\"")]
[InlineData(LoggingLevel.Error, "\"error\"")]
[InlineData(LoggingLevel.Critical, "\"critical\"")]
[InlineData(LoggingLevel.Alert, "\"alert\"")]
[InlineData(LoggingLevel.Emergency, "\"emergency\"")]
public static void SerializeLoggingLevel_ShouldBeCamelCased(LoggingLevel level, string expectedValue)
{
var actualValue = JsonSerializer.Serialize(level);

Assert.Equal(expectedValue, actualValue);
}

[Theory]
[InlineData(ContextInclusion.None, "\"none\"")]
[InlineData(ContextInclusion.ThisServer, "\"thisServer\"")]
[InlineData(ContextInclusion.AllServers, "\"allServers\"")]
public static void ContextInclusion_ShouldBeCamelCased(ContextInclusion level, string expectedValue)
{
var actualValue = JsonSerializer.Serialize(level);

Assert.Equal(expectedValue, actualValue);
}
}