Use DescriptionAttribute and HasDefaultValue in server builder extensions (#46)

This commit is contained in:
Stephen Toub 2025-03-09 06:16:00 -04:00 • committed by GitHub
commit 33d2b0d762
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 61 deletions

View file

@ -1,4 +1,5 @@
using System.Globalization;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Text.Json;
using McpDotNet.Configuration;
@ -117,7 +118,7 @@ public static partial class McpServerBuilderExtensions
return WithTools(builder, toolTypes.ToArray());
}
private static Tool CreateTool(MethodInfo method, McpToolAttribute attribute)
private static Tool CreateTool(MethodInfo method, McpToolAttribute mcpAttribute)
{
Dictionary<string, JsonSchemaProperty> properties = [];
List<string>? requiredProperties = null;
@ -127,15 +128,15 @@ public static partial class McpServerBuilderExtensions
if (parameter.ParameterType == typeof(CancellationToken))
continue;
var parameterAttribute = parameter.GetCustomAttribute<McpParameterAttribute>();
var parameterDescriptionAttr = parameter.GetCustomAttribute<DescriptionAttribute>();
properties.Add(parameter.Name ?? "NoName", new JsonSchemaProperty()
{
Type = GetParameterType(parameter.ParameterType),
Description = parameterAttribute?.Description
Description = parameterDescriptionAttr?.Description,
});
if (parameterAttribute?.Required == true)
if (!parameter.HasDefaultValue)
{
requiredProperties ??= [];
requiredProperties.Add(parameter.Name ?? "NoName");
@ -144,8 +145,8 @@ public static partial class McpServerBuilderExtensions
return new Tool()
{
Name = attribute.Name ?? method.Name,
Description = attribute.Description,
Name = mcpAttribute.Name ?? method.Name,
Description = method.GetCustomAttribute<DescriptionAttribute>()?.Description,
InputSchema = new JsonSchema()
{
Type = "object",
@ -229,12 +230,10 @@ public static partial class McpServerBuilderExtensions
}
else
{
var parameterAttribute = parameter.GetCustomAttribute<McpParameterAttribute>();
if (parameterAttribute?.Required == true)
if (!parameter.HasDefaultValue)
throw new McpServerException($"Missing required argument '{parameter.Name}'.");
parameters.Add(parameter.HasDefaultValue ? parameter.DefaultValue : null);
parameters.Add(parameter.DefaultValue);
}
}

View file

@ -1,29 +0,0 @@
namespace McpDotNet.Server;
/// <summary>
/// Attribute to mark a method parameter
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class McpParameterAttribute : Attribute
{
/// <summary>
/// Defines if the parameter is required.
/// </summary>
public bool Required { get; }
/// <summary>
/// A description of the parameter.
/// </summary>
public string? Description { get; }
/// <summary>
/// Attribute to mark a method as an MCP tool.
/// </summary>
/// <param name="required">True if the parameter is mandatory.</param>
/// <param name="description">A description of the tool.</param>
public McpParameterAttribute(bool required = false, string? description = null)
{
Required = required;
Description = description;
}
}

View file

@ -6,22 +6,15 @@
[AttributeUsage(AttributeTargets.Method)]
public sealed class McpToolAttribute : Attribute
{
/// The name of the tool. If not provided, the class name will be used.
/// <summary>Gets the name of the tool.</summary>
/// <remarks>If not provided, the method name will be used.</remarks>
public string? Name { get; }
/// <summary>
/// A description of the tool.
/// </summary>
public string? Description { get; }
/// <summary>
/// Attribute to mark a method as an MCP tool.
/// </summary>
/// <param name="name">The name of the tool. If not provided, the class name will be used.</param>
/// <param name="description">A description of the tool.</param>
public McpToolAttribute(string? name = null, string? description = null)
public McpToolAttribute(string? name = null)
{
Name = name;
Description = description;
}
}