Add ToolAnnotations support (#124)
* Add ToolAnnotations support * Address feedback
This commit is contained in:
parent
2c1672cc1a
commit
62e92fa154
5 changed files with 645 additions and 394 deletions
|
|
@ -21,13 +21,13 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
/// </summary>
|
||||
public static new AIFunctionMcpServerTool Create(
|
||||
Delegate method,
|
||||
string? name,
|
||||
string? description,
|
||||
IServiceProvider? services)
|
||||
McpServerToolCreateOptions? options)
|
||||
{
|
||||
Throw.IfNull(method);
|
||||
|
||||
options = DeriveOptions(method.Method, options);
|
||||
|
||||
return Create(method.Method, method.Target, name, description, services);
|
||||
return Create(method.Method, method.Target, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -36,9 +36,7 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
public static new AIFunctionMcpServerTool Create(
|
||||
MethodInfo method,
|
||||
object? target,
|
||||
string? name,
|
||||
string? description,
|
||||
IServiceProvider? services)
|
||||
McpServerToolCreateOptions? options)
|
||||
{
|
||||
Throw.IfNull(method);
|
||||
|
||||
|
|
@ -49,7 +47,11 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
// AIFunctionFactory, delete the TemporaryXx types, and fix-up the mechanism by
|
||||
// which the arguments are passed.
|
||||
|
||||
return Create(TemporaryAIFunctionFactory.Create(method, target, CreateAIFunctionFactoryOptions(method, name, description, services)));
|
||||
options = DeriveOptions(method, options);
|
||||
|
||||
return Create(
|
||||
TemporaryAIFunctionFactory.Create(method, target, CreateAIFunctionFactoryOptions(method, options)),
|
||||
options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -58,21 +60,23 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
public static new AIFunctionMcpServerTool Create(
|
||||
MethodInfo method,
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type targetType,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IServiceProvider? services = null)
|
||||
McpServerToolCreateOptions? options)
|
||||
{
|
||||
Throw.IfNull(method);
|
||||
|
||||
return Create(TemporaryAIFunctionFactory.Create(method, targetType, CreateAIFunctionFactoryOptions(method, name, description, services)));
|
||||
options = DeriveOptions(method, options);
|
||||
|
||||
return Create(
|
||||
TemporaryAIFunctionFactory.Create(method, targetType, CreateAIFunctionFactoryOptions(method, options)),
|
||||
options);
|
||||
}
|
||||
|
||||
private static TemporaryAIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
|
||||
MethodInfo method, string? name, string? description, IServiceProvider? services) =>
|
||||
new TemporaryAIFunctionFactoryOptions()
|
||||
MethodInfo method, McpServerToolCreateOptions? options) =>
|
||||
new()
|
||||
{
|
||||
Name = name ?? method.GetCustomAttribute<McpServerToolAttribute>()?.Name,
|
||||
Description = description,
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerToolAttribute>()?.Name,
|
||||
Description = options?.Description,
|
||||
MarshalResult = static (result, _, cancellationToken) => Task.FromResult(result),
|
||||
ConfigureParameterBinding = pi =>
|
||||
{
|
||||
|
|
@ -97,7 +101,7 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
// We assume that if the services used to create the tool support a particular type,
|
||||
// so too do the services associated with the server. This is the same basic assumption
|
||||
// made in ASP.NET.
|
||||
if (services is not null &&
|
||||
if (options?.Services is { } services &&
|
||||
services.GetService<IServiceProviderIsService>() is { } ispis &&
|
||||
ispis.IsService(pi.ParameterType))
|
||||
{
|
||||
|
|
@ -139,26 +143,80 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
};
|
||||
|
||||
/// <summary>Creates an <see cref="McpServerTool"/> that wraps the specified <see cref="AIFunction"/>.</summary>
|
||||
public static new AIFunctionMcpServerTool Create(AIFunction function)
|
||||
public static new AIFunctionMcpServerTool Create(AIFunction function, McpServerToolCreateOptions? options)
|
||||
{
|
||||
Throw.IfNull(function);
|
||||
|
||||
return new AIFunctionMcpServerTool(function);
|
||||
Tool tool = new()
|
||||
{
|
||||
Name = options?.Name ?? function.Name,
|
||||
Description = options?.Description ?? function.Description,
|
||||
InputSchema = function.JsonSchema,
|
||||
};
|
||||
|
||||
if (options is not null)
|
||||
{
|
||||
if (options.Title is not null ||
|
||||
options.Idempotent is not null ||
|
||||
options.Destructive is not null ||
|
||||
options.OpenWorld is not null ||
|
||||
options.ReadOnly is not null)
|
||||
{
|
||||
tool.Annotations = new()
|
||||
{
|
||||
Title = options?.Title,
|
||||
IdempotentHint = options?.Idempotent,
|
||||
DestructiveHint = options?.Destructive,
|
||||
OpenWorldHint = options?.OpenWorld,
|
||||
ReadOnlyHint = options?.ReadOnly,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return new AIFunctionMcpServerTool(function, tool);
|
||||
}
|
||||
|
||||
private static McpServerToolCreateOptions? DeriveOptions(MethodInfo method, McpServerToolCreateOptions? options)
|
||||
{
|
||||
McpServerToolCreateOptions newOptions = options?.Clone() ?? new();
|
||||
|
||||
if (method.GetCustomAttribute<McpServerToolAttribute>() is { } attr)
|
||||
{
|
||||
newOptions.Name ??= attr.Name;
|
||||
newOptions.Title ??= attr.Title;
|
||||
|
||||
if (attr._destructive is bool destructive)
|
||||
{
|
||||
newOptions.Destructive ??= destructive;
|
||||
}
|
||||
|
||||
if (attr._idempotent is bool idempotent)
|
||||
{
|
||||
newOptions.Idempotent ??= idempotent;
|
||||
}
|
||||
|
||||
if (attr._openWorld is bool openWorld)
|
||||
{
|
||||
newOptions.OpenWorld ??= openWorld;
|
||||
}
|
||||
|
||||
if (attr._readOnly is bool readOnly)
|
||||
{
|
||||
newOptions.ReadOnly ??= readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
/// <summary>Gets the <see cref="AIFunction"/> wrapped by this tool.</summary>
|
||||
internal AIFunction AIFunction { get; }
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="McpServerTool"/> class.</summary>
|
||||
private AIFunctionMcpServerTool(AIFunction function)
|
||||
private AIFunctionMcpServerTool(AIFunction function, Tool tool)
|
||||
{
|
||||
AIFunction = function;
|
||||
ProtocolTool = new()
|
||||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
InputSchema = function.JsonSchema,
|
||||
};
|
||||
ProtocolTool = tool;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -201,30 +259,37 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
{
|
||||
Content = [aiContent.ToContent()]
|
||||
},
|
||||
|
||||
null => new()
|
||||
{
|
||||
Content = []
|
||||
},
|
||||
|
||||
string text => new()
|
||||
{
|
||||
Content = [new() { Text = text, Type = "text" }]
|
||||
},
|
||||
|
||||
Content content => new()
|
||||
{
|
||||
Content = [content]
|
||||
},
|
||||
|
||||
IEnumerable<string> texts => new()
|
||||
{
|
||||
Content = [.. texts.Select(x => new Content() { Type = "text", Text = x ?? string.Empty })]
|
||||
},
|
||||
|
||||
IEnumerable<AIContent> contentItems => new()
|
||||
{
|
||||
Content = [.. contentItems.Select(static item => item.ToContent())]
|
||||
},
|
||||
|
||||
IEnumerable<Content> contents => new()
|
||||
{
|
||||
Content = [.. contents]
|
||||
},
|
||||
|
||||
CallToolResponse callToolResponse => callToolResponse,
|
||||
|
||||
// TODO https://github.com/modelcontextprotocol/csharp-sdk/issues/69:
|
||||
|
|
@ -232,10 +297,10 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
|
|||
_ => new()
|
||||
{
|
||||
Content = [new()
|
||||
{
|
||||
Text = JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object))),
|
||||
Type = "text"
|
||||
}]
|
||||
{
|
||||
Text = JsonSerializer.Serialize(result, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object))),
|
||||
Type = "text"
|
||||
}]
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,13 +88,13 @@ public static class McpServerExtensions
|
|||
});
|
||||
break;
|
||||
|
||||
case DataContent dataContent when dataContent.HasTopLevelMediaType("image"):
|
||||
case DataContent dataContent when dataContent.HasTopLevelMediaType("image") || dataContent.HasTopLevelMediaType("audio"):
|
||||
samplingMessages.Add(new()
|
||||
{
|
||||
Role = role,
|
||||
Content = new()
|
||||
{
|
||||
Type = "image",
|
||||
Type = dataContent.HasTopLevelMediaType("image") ? "image" : "audio",
|
||||
MimeType = dataContent.MediaType,
|
||||
Data = dataContent.GetBase64Data(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using Microsoft.Extensions.AI;
|
||||
using ModelContextProtocol.Protocol.Types;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
|
||||
|
|
@ -30,58 +29,28 @@ public abstract class McpServerTool
|
|||
/// Creates an <see cref="McpServerTool"/> instance for a method, specified via a <see cref="Delegate"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="method">The method to be represented via the created <see cref="McpServerTool"/>.</param>
|
||||
/// <param name="name">
|
||||
/// The name to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but an <see cref="McpServerToolAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the name from the attribute will be used. If that's not present, the name based
|
||||
/// on <paramref name="method"/>'s name will be used.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// The description to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but a <see cref="DescriptionAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the description from that attribute will be used.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional services used in the construction of the <see cref="McpServerTool"/>. These services will be
|
||||
/// used to determine which parameters should be satisifed from dependency injection; what services
|
||||
/// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time.
|
||||
/// </param>
|
||||
/// <param name="options">Optional options used in the creation of the <see cref="McpServerTool"/> to control its behavior.</param>
|
||||
/// <returns>The created <see cref="McpServerTool"/> for invoking <paramref name="method"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="method"/> is <see langword="null"/>.</exception>
|
||||
public static McpServerTool Create(
|
||||
Delegate method,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IServiceProvider? services = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, name, description, services);
|
||||
McpServerToolCreateOptions? options = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, options);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="McpServerTool"/> instance for a method, specified via a <see cref="Delegate"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="method">The method to be represented via the created <see cref="McpServerTool"/>.</param>
|
||||
/// <param name="target">The instance if <paramref name="method"/> is an instance method; otherwise, <see langword="null"/>.</param>
|
||||
/// <param name="name">
|
||||
/// The name to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but an <see cref="McpServerToolAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the name from the attribute will be used. If that's not present, the name based
|
||||
/// on <paramref name="method"/>'s name will be used.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// The description to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but a <see cref="DescriptionAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the description from that attribute will be used.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional services used in the construction of the <see cref="McpServerTool"/>. These services will be
|
||||
/// used to determine which parameters should be satisifed from dependency injection; what services
|
||||
/// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time.
|
||||
/// </param>
|
||||
/// <param name="options">Optional options used in the creation of the <see cref="McpServerTool"/> to control its behavior.</param>
|
||||
/// <returns>The created <see cref="McpServerTool"/> for invoking <paramref name="method"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="method"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="method"/> is an instance method but <paramref name="target"/> is <see langword="null"/>.</exception>
|
||||
public static McpServerTool Create(
|
||||
MethodInfo method,
|
||||
object? target = null,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IServiceProvider? services = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, target, name, description, services);
|
||||
McpServerToolCreateOptions? options = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, target, options);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="McpServerTool"/> instance for a method, specified via an <see cref="MethodInfo"/> for
|
||||
|
|
@ -96,39 +65,27 @@ public abstract class McpServerTool
|
|||
/// <see cref="Activator.CreateInstance(Type)"/> is used, utilizing the type's public parameterless constructor.
|
||||
/// If an instance can't be constructed, an exception is thrown during the function's invocation.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// The name to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but an <see cref="McpServerToolAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the name from the attribute will be used. If that's not present, the name based
|
||||
/// on <paramref name="method"/>'s name will be used.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// The description to use for the <see cref="McpServerTool"/>. If <see langword="null"/>, but a <see cref="DescriptionAttribute"/>
|
||||
/// is applied to <paramref name="method"/>, the description from that attribute will be used.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional services used in the construction of the <see cref="McpServerTool"/>. These services will be
|
||||
/// used to determine which parameters should be satisifed from dependency injection; what services
|
||||
/// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time.
|
||||
/// </param>
|
||||
/// <param name="options">Optional options used in the creation of the <see cref="McpServerTool"/> to control its behavior.</param>
|
||||
/// <returns>The created <see cref="AIFunction"/> for invoking <paramref name="method"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="method"/> is <see langword="null"/>.</exception>
|
||||
public static McpServerTool Create(
|
||||
MethodInfo method,
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type targetType,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IServiceProvider? services = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, targetType, name, description, services);
|
||||
McpServerToolCreateOptions? options = null) =>
|
||||
AIFunctionMcpServerTool.Create(method, targetType, options);
|
||||
|
||||
/// <summary>Creates an <see cref="McpServerTool"/> that wraps the specified <see cref="AIFunction"/>.</summary>
|
||||
/// <param name="function">The function to wrap.</param>
|
||||
/// <param name="options">Optional options used in the creation of the <see cref="McpServerTool"/> to control its behavior.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="function"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// Unlike the other overloads of Create, the <see cref="McpServerTool"/> created by <see cref="Create(AIFunction)"/>
|
||||
/// Unlike the other overloads of Create, the <see cref="McpServerTool"/> created by <see cref="Create(AIFunction, McpServerToolCreateOptions)"/>
|
||||
/// does not provide all of the special parameter handling for MCP-specific concepts, like <see cref="IMcpServer"/>.
|
||||
/// </remarks>
|
||||
public static McpServerTool Create(AIFunction function) =>
|
||||
AIFunctionMcpServerTool.Create(function);
|
||||
public static McpServerTool Create(
|
||||
AIFunction function,
|
||||
McpServerToolCreateOptions? options = null) =>
|
||||
AIFunctionMcpServerTool.Create(function, options);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => ProtocolTool.Name;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,73 @@
|
|||
namespace ModelContextProtocol.Server;
|
||||
|
||||
/// <summary>
|
||||
/// Used to mark a public method as an MCP tool.
|
||||
/// Used to indicate that a method should be considered an MCP tool and describe it.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class McpServerToolAttribute : Attribute
|
||||
{
|
||||
/// <summary>Gets the name of the tool.</summary>
|
||||
/// <remarks>If <see langword="null"/>, the method name will be used.</remarks>
|
||||
public string? Name { get; }
|
||||
// Defaults based on the spec
|
||||
private const bool DestructiveDefault = true;
|
||||
private const bool IdempotentDefault = false;
|
||||
private const bool OpenWorldDefault = true;
|
||||
private const bool ReadOnlyDefault = false;
|
||||
|
||||
// Nullable backing fields so we can distinguish
|
||||
internal bool? _destructive;
|
||||
internal bool? _idempotent;
|
||||
internal bool? _openWorld;
|
||||
internal bool? _readOnly;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="McpServerToolTypeAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tool. If <see langword="null"/>, the method name will be used.</param>
|
||||
public McpServerToolAttribute(string? name = null) => Name = name;
|
||||
public McpServerToolAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the tool.</summary>
|
||||
/// <remarks>If <see langword="null"/>, the method name will be used.</remarks>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a human-readable title for the tool.
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the tool may perform destructive updates to its environment.
|
||||
/// </summary>
|
||||
public bool Destructive
|
||||
{
|
||||
get => _destructive ?? DestructiveDefault;
|
||||
set => _destructive = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether calling the tool repeatedly with the same arguments will have no additional effect on its environment.
|
||||
/// </summary>
|
||||
public bool Idempotent
|
||||
{
|
||||
get => _idempotent ?? IdempotentDefault;
|
||||
set => _idempotent = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this tool may interact with an "open world" of external entities
|
||||
/// (e.g. the world of a web search tool is open, whereas that of a memory tool is not).
|
||||
/// </summary>
|
||||
public bool OpenWorld
|
||||
{
|
||||
get => _openWorld ?? OpenWorldDefault;
|
||||
set => _openWorld = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the tool does not modify its environment.
|
||||
/// </summary>
|
||||
public bool ReadOnly
|
||||
{
|
||||
get => _readOnly ?? ReadOnlyDefault;
|
||||
set => _readOnly = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace ModelContextProtocol.Server;
|
||||
|
||||
/// <summary>Provides options for controlling the creation of an <see cref="McpServerTool"/>.</summary>
|
||||
public sealed class McpServerToolCreateOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets optional services used in the construction of the <see cref="McpServerTool"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These services will be used to determine which parameters should be satisifed from dependency injection; what services
|
||||
/// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time.
|
||||
/// </remarks>
|
||||
public IServiceProvider? Services { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to use for the <see cref="McpServerTool"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see langword="null"/>, but an <see cref="McpServerToolAttribute"/> is applied to the method,
|
||||
/// the name from the attribute will be used. If that's not present, a name based on the method's name will be used.
|
||||
/// </remarks>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the description to use for the <see cref="McpServerTool"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see langword="null"/>, but a <see cref="DescriptionAttribute"/> is applied to the method,
|
||||
/// the description from that attribute will be used.
|
||||
/// </remarks>
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a human-readable title for the tool.
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the tool may perform destructive updates to its environment.
|
||||
/// </summary>
|
||||
public bool? Destructive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether calling the tool repeatedly with the same arguments
|
||||
/// will have no additional effect on its environment.
|
||||
/// </summary>
|
||||
public bool? Idempotent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this tool may interact with an "open world" of external entities.
|
||||
/// </summary>
|
||||
public bool? OpenWorld { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this tool does not modify its environment.
|
||||
/// </summary>
|
||||
public bool? ReadOnly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a shallow clone of the current <see cref="McpServerToolCreateOptions"/> instance.
|
||||
/// </summary>
|
||||
internal McpServerToolCreateOptions Clone() =>
|
||||
new McpServerToolCreateOptions()
|
||||
{
|
||||
Services = Services,
|
||||
Name = Name,
|
||||
Description = Description,
|
||||
Title = Title,
|
||||
Destructive = Destructive,
|
||||
Idempotent = Idempotent,
|
||||
OpenWorld = OpenWorld,
|
||||
ReadOnly = ReadOnly
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue