Skip to content

Commit 9e8de5c

Browse files
committed
Change approach and add lots of tests
1 parent 3c597d6 commit 9e8de5c

File tree

4 files changed

+1291
-54
lines changed

4 files changed

+1291
-54
lines changed

samples/AspNetCoreMcpServer/Tools/WeatherTools.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public WeatherTools(IHttpClientFactory httpClientFactory)
1717
}
1818

1919
[McpServerTool, Description("Get weather alerts for a US state.")]
20-
[McpMeta("category", "\"weather\"")]
21-
[McpMeta("dataSource", "\"weather.gov\"")]
20+
[McpMeta("category", "weather")]
21+
[McpMeta("dataSource", "weather.gov")]
2222
public async Task<string> GetAlerts(
2323
[Description("The US state to get alerts for. Use the 2 letter abbreviation for the state (e.g. NY).")] string state)
2424
{
@@ -48,8 +48,8 @@ public async Task<string> GetAlerts(
4848
}
4949

5050
[McpServerTool, Description("Get weather forecast for a location.")]
51-
[McpMeta("category", "\"weather\"")]
52-
[McpMeta("recommendedModel", "\"gpt-4\"")]
51+
[McpMeta("category", "weather")]
52+
[McpMeta("recommendedModel", "gpt-4")]
5353
public async Task<string> GetForecast(
5454
[Description("Latitude of the location.")] double latitude,
5555
[Description("Longitude of the location.")] double longitude)

src/ModelContextProtocol.Core/Server/AIFunctionMcpServerTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ internal static IReadOnlyList<object> CreateMetadata(MethodInfo method)
369369
{
370370
if (meta?.ContainsKey(attr.Name) is not true)
371371
{
372-
(meta ??= [])[attr.Name] = JsonNode.Parse(attr.Value);
372+
(meta ??= [])[attr.Name] = JsonNode.Parse(attr.JsonValue);
373373
}
374374
}
375375

src/ModelContextProtocol.Core/Server/McpMetaAttribute.cs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using ModelContextProtocol.Protocol;
22
using System.Diagnostics.CodeAnalysis;
3+
using System.Text.Json;
4+
using System.Text.Json.Nodes;
35

46
namespace ModelContextProtocol.Server;
57

@@ -20,28 +22,52 @@ namespace ModelContextProtocol.Server;
2022
/// Metadata can be used to attach additional information to primitives, such as model preferences,
2123
/// version information, or other custom data that should be communicated to MCP clients.
2224
/// </para>
25+
/// </remarks>
2326
/// <example>
2427
/// <code>
2528
/// [McpServerTool]
26-
/// [McpMeta("model", "\"gpt-4o\"")]
27-
/// [McpMeta("version", "\"1.0\"")]
28-
/// [McpMeta("priority", "5")]
29+
/// [McpMeta("model", "gpt-4o")]
30+
/// [McpMeta("version", "1.0")]
31+
/// [McpMeta("priority", 5.0)]
32+
/// [McpMeta("isBeta", true)]
33+
/// [McpMeta("tags", JsonValue = """["a","b"]""")]
2934
/// public string MyTool(string input) => $"Processed: {input}";
3035
/// </code>
3136
/// </example>
32-
/// </remarks>
3337
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
3438
public sealed class McpMetaAttribute : Attribute
3539
{
3640
/// <summary>
37-
/// Initializes a new instance of the <see cref="McpMetaAttribute"/> class.
41+
/// Initializes a new instance of the <see cref="McpMetaAttribute"/> class with a string value.
42+
/// </summary>
43+
/// <param name="name">The name (key) of the metadata entry.</param>
44+
/// <param name="value">The string value of the metadata entry. If null, the value will be serialized as JSON null.</param>
45+
public McpMetaAttribute(string name, string? value = null)
46+
{
47+
Name = name;
48+
JsonValue = value is null ? "null" : JsonSerializer.Serialize(value, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(string)));
49+
}
50+
51+
/// <summary>
52+
/// Initializes a new instance of the <see cref="McpMetaAttribute"/> class with a double value.
3853
/// </summary>
3954
/// <param name="name">The name (key) of the metadata entry.</param>
40-
/// <param name="value">The value of the metadata entry as a JSON string. This must be well-formed JSON.</param>
41-
public McpMetaAttribute(string name, [StringSyntax(StringSyntaxAttribute.Json)] string value)
55+
/// <param name="value">The double value of the metadata entry.</param>
56+
public McpMetaAttribute(string name, double value)
4257
{
4358
Name = name;
44-
Value = value;
59+
JsonValue = JsonSerializer.Serialize(value, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(double)));
60+
}
61+
62+
/// <summary>
63+
/// Initializes a new instance of the <see cref="McpMetaAttribute"/> class with a boolean value.
64+
/// </summary>
65+
/// <param name="name">The name (key) of the metadata entry.</param>
66+
/// <param name="value">The boolean value of the metadata entry.</param>
67+
public McpMetaAttribute(string name, bool value)
68+
{
69+
Name = name;
70+
JsonValue = value ? "true" : "false";
4571
}
4672

4773
/// <summary>
@@ -54,21 +80,24 @@ public McpMetaAttribute(string name, [StringSyntax(StringSyntaxAttribute.Json)]
5480
public string Name { get; }
5581

5682
/// <summary>
57-
/// Gets the value of the metadata entry as a JSON string.
83+
/// Gets or sets the value of the metadata entry as a JSON string.
5884
/// </summary>
5985
/// <remarks>
6086
/// <para>
61-
/// This value must be well-formed JSON. It will be parsed and added to the metadata JsonObject.
87+
/// This value must be well-formed JSON. It will be parsed and added to the metadata <see cref="JsonObject"/>.
6288
/// Simple values can be represented as JSON literals like <c>"\"my-string\""</c>, <c>"123"</c>,
6389
/// <c>"true"</c>, etc. Complex structures can be represented as JSON objects or arrays.
6490
/// </para>
6591
/// <para>
92+
/// Setting this property will override any value provided via the constructor.
93+
/// </para>
94+
/// <para>
6695
/// For programmatic scenarios where you want to construct complex metadata without dealing with
6796
/// JSON strings, use the <see cref="McpServerToolCreateOptions.Meta"/>,
6897
/// <see cref="McpServerPromptCreateOptions.Meta"/>, or <see cref="McpServerResourceCreateOptions.Meta"/>
6998
/// property to provide a JsonObject directly.
7099
/// </para>
71100
/// </remarks>
72101
[StringSyntax(StringSyntaxAttribute.Json)]
73-
public string Value { get; }
102+
public string JsonValue { get; set; }
74103
}

0 commit comments

Comments
 (0)