Change type of Tool.InputSchema to be JsonElement (#4)
* Change type of Tool.InputSchema to be JsonElement * Add schema validation in the InputSchema property setter. * Simplify AIFunction tool adapter. --------- Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
This commit is contained in:
parent
d23e065945
commit
3de19d38e4
6 changed files with 175 additions and 128 deletions
|
|
@ -466,8 +466,6 @@ public static class McpClientExtensions
|
|||
/// <summary>Provides an AI function that calls a tool through <see cref="IMcpClient"/>.</summary>
|
||||
private sealed class McpAIFunction(IMcpClient client, Tool tool) : AIFunction
|
||||
{
|
||||
private JsonElement? _jsonSchema;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => tool.Name;
|
||||
|
||||
|
|
@ -475,15 +473,7 @@ public static class McpClientExtensions
|
|||
public override string Description => tool.Description ?? string.Empty;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override JsonElement JsonSchema => _jsonSchema ??=
|
||||
JsonSerializer.SerializeToElement(new Dictionary<string, object>
|
||||
{
|
||||
["type"] = "object",
|
||||
["title"] = tool.Name,
|
||||
["description"] = tool.Description ?? string.Empty,
|
||||
["properties"] = tool.InputSchema?.Properties ?? [],
|
||||
["required"] = tool.InputSchema?.Required ?? []
|
||||
}, McpJsonUtilities.JsonContext.Default.DictionaryStringObject);
|
||||
public override JsonElement JsonSchema => tool.InputSchema;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected async override Task<object?> InvokeCoreAsync(
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public static partial class McpServerBuilderExtensions
|
|||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
InputSchema = JsonSerializer.Deserialize(function.JsonSchema, McpJsonUtilities.JsonContext.Default.JsonSchema),
|
||||
InputSchema = function.JsonSchema,
|
||||
});
|
||||
|
||||
callbacks.Add(function.Name, async (request, cancellationToken) =>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
namespace ModelContextProtocol.Protocol.Types;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a JSON schema for a tool's input arguments.
|
||||
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
|
||||
/// </summary>
|
||||
public class JsonSchema
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of the schema, should be "object".
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; } = "object";
|
||||
|
||||
/// <summary>
|
||||
/// Map of property names to property definitions.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("properties")]
|
||||
public Dictionary<string, JsonSchemaProperty>? Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of required property names.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("required")]
|
||||
public List<string>? Required { get; set; }
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
namespace ModelContextProtocol.Protocol.Types;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a property in a JSON schema.
|
||||
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
|
||||
/// </summary>
|
||||
public class JsonSchemaProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of the property. Should be a JSON Schema type and is required.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// A human-readable description of the property.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("description")]
|
||||
public string? Description { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using ModelContextProtocol.Utils.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol.Types;
|
||||
|
||||
|
|
@ -23,6 +25,23 @@ public class Tool
|
|||
/// <summary>
|
||||
/// A JSON Schema object defining the expected parameters for the tool.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Needs to a valid JSON schema object that additionally is of type object.
|
||||
/// </remarks>
|
||||
[JsonPropertyName("inputSchema")]
|
||||
public JsonSchema? InputSchema { get; set; }
|
||||
public JsonElement InputSchema
|
||||
{
|
||||
get => _inputSchema;
|
||||
set
|
||||
{
|
||||
if (!McpJsonUtilities.IsValidMcpToolSchema(value))
|
||||
{
|
||||
throw new ArgumentException("The specified document is not a valid MPC tool JSON schema.", nameof(InputSchema));
|
||||
}
|
||||
|
||||
_inputSchema = value;
|
||||
}
|
||||
}
|
||||
|
||||
private JsonElement _inputSchema = McpJsonUtilities.DefaultMcpToolSchema;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,31 @@ public static partial class McpJsonUtilities
|
|||
internal static JsonTypeInfo<T> GetTypeInfo<T>(this JsonSerializerOptions options) =>
|
||||
(JsonTypeInfo<T>)options.GetTypeInfo(typeof(T));
|
||||
|
||||
internal static JsonElement DefaultMcpToolSchema = ParseJsonElement("{\"type\":\"object\"}"u8);
|
||||
internal static bool IsValidMcpToolSchema(JsonElement element)
|
||||
{
|
||||
if (element.ValueKind is not JsonValueKind.Object)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (JsonProperty property in element.EnumerateObject())
|
||||
{
|
||||
if (property.NameEquals("type"))
|
||||
{
|
||||
if (property.Value.ValueKind is not JsonValueKind.String ||
|
||||
!property.Value.ValueEquals("object"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // No need to check other properties
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No type keyword found.
|
||||
}
|
||||
|
||||
// Keep in sync with CreateDefaultOptions above.
|
||||
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web,
|
||||
UseStringEnumConverter = true,
|
||||
|
|
@ -96,7 +121,13 @@ public static partial class McpJsonUtilities
|
|||
[JsonSerializable(typeof(CreateMessageResult))]
|
||||
[JsonSerializable(typeof(ListRootsResult))]
|
||||
[JsonSerializable(typeof(InitializeResult))]
|
||||
[JsonSerializable(typeof(JsonSchema))]
|
||||
[JsonSerializable(typeof(CallToolResponse))]
|
||||
internal sealed partial class JsonContext : JsonSerializerContext;
|
||||
|
||||
private static JsonElement ParseJsonElement(ReadOnlySpan<byte> utf8Json)
|
||||
{
|
||||
Utf8JsonReader reader = new(utf8Json);
|
||||
return JsonElement.ParseValue(ref reader);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue