Skip to content

Commit 3ab5541

Browse files
Copilotstephentoub
andcommitted
Make Name and Value constructor parameters in McpMetaAttribute and check AIFunction.Metadata.UnderlyingMethod
Co-authored-by: stephentoub <[email protected]>
1 parent d5413d7 commit 3ab5541

File tree

6 files changed

+33
-26
lines changed

6 files changed

+33
-26
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(Name = "category", Value = "weather")]
21-
[McpMeta(Name = "dataSource", Value = "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(Name = "category", Value = "weather")]
52-
[McpMeta(Name = "recommendedModel", Value = "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/AIFunctionMcpServerPrompt.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,11 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
139139
Icons = options?.Icons,
140140
};
141141

142-
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is in the metadata
143-
if (options?.Metadata?.FirstOrDefault(m => m is MethodInfo) is MethodInfo method)
142+
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is available
143+
MethodInfo? method = options?.Metadata?.FirstOrDefault(m => m is MethodInfo) as MethodInfo ?? function.Metadata?.UnderlyingMethod;
144+
if (method is not null)
144145
{
145-
prompt.Meta = AIFunctionMcpServerTool.CreateMetaFromAttributes(method, options.Meta);
146+
prompt.Meta = AIFunctionMcpServerTool.CreateMetaFromAttributes(method, options?.Meta);
146147
}
147148
else if (options?.Meta is not null)
148149
{

src/ModelContextProtocol.Core/Server/AIFunctionMcpServerResource.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,12 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
212212

213213
string name = options?.Name ?? function.Name;
214214

215-
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is in the metadata
215+
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is available
216+
MethodInfo? method = options?.Metadata?.FirstOrDefault(m => m is MethodInfo) as MethodInfo ?? function.Metadata?.UnderlyingMethod;
216217
JsonObject? meta = null;
217-
if (options?.Metadata?.FirstOrDefault(m => m is MethodInfo) is MethodInfo method)
218+
if (method is not null)
218219
{
219-
meta = AIFunctionMcpServerTool.CreateMetaFromAttributes(method, options.Meta);
220+
meta = AIFunctionMcpServerTool.CreateMetaFromAttributes(method, options?.Meta);
220221
}
221222
else if (options?.Meta is not null)
222223
{

src/ModelContextProtocol.Core/Server/AIFunctionMcpServerTool.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ options.OpenWorld is not null ||
144144
};
145145
}
146146

147-
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is in the metadata
148-
if (options.Metadata?.FirstOrDefault(m => m is MethodInfo) is MethodInfo method)
147+
// Populate Meta from options and/or McpMetaAttribute instances if a MethodInfo is available
148+
MethodInfo? method = options.Metadata?.FirstOrDefault(m => m is MethodInfo) as MethodInfo ?? function.Metadata?.UnderlyingMethod;
149+
if (method is not null)
149150
{
150151
tool.Meta = CreateMetaFromAttributes(method, options.Meta);
151152
}

src/ModelContextProtocol.Core/Server/McpMetaAttribute.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ namespace ModelContextProtocol.Server;
1818
/// <example>
1919
/// <code>
2020
/// [McpServerTool]
21-
/// [McpMeta(Name = "model", Value = "gpt-4o")]
22-
/// [McpMeta(Name = "version", Value = "1.0")]
21+
/// [McpMeta("model", "gpt-4o")]
22+
/// [McpMeta("version", "1.0")]
2323
/// public string MyTool(string input)
2424
/// {
2525
/// return $"Processed: {input}";
@@ -33,26 +33,30 @@ public sealed class McpMetaAttribute : Attribute
3333
/// <summary>
3434
/// Initializes a new instance of the <see cref="McpMetaAttribute"/> class.
3535
/// </summary>
36-
public McpMetaAttribute()
36+
/// <param name="name">The name (key) of the metadata entry.</param>
37+
/// <param name="value">The value of the metadata entry.</param>
38+
public McpMetaAttribute(string name, string value)
3739
{
40+
Name = name;
41+
Value = value;
3842
}
3943

4044
/// <summary>
41-
/// Gets or sets the name (key) of the metadata entry.
45+
/// Gets the name (key) of the metadata entry.
4246
/// </summary>
4347
/// <remarks>
4448
/// This value is used as the key in the metadata object. It should be a unique identifier
4549
/// for this piece of metadata within the context of the primitive.
4650
/// </remarks>
47-
public required string Name { get; set; }
51+
public string Name { get; }
4852

4953
/// <summary>
50-
/// Gets or sets the value of the metadata entry.
54+
/// Gets the value of the metadata entry.
5155
/// </summary>
5256
/// <remarks>
5357
/// This value is stored as a string in the metadata object. For complex values, use the
5458
/// <see cref="McpServerToolCreateOptions.Meta"/>, <see cref="McpServerPromptCreateOptions.Meta"/>,
5559
/// or <see cref="McpServerResourceCreateOptions.Meta"/> property to provide a JsonObject directly.
5660
/// </remarks>
57-
public required string Value { get; set; }
61+
public string Value { get; }
5862
}

tests/ModelContextProtocol.Tests/Server/McpMetaAttributeTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ public void McpMetaAttribute_ResourceOptionsMetaTakesPrecedence()
178178
private class TestToolClass
179179
{
180180
[McpServerTool]
181-
[McpMeta(Name = "model", Value = "gpt-4o")]
182-
[McpMeta(Name = "version", Value = "1.0")]
181+
[McpMeta("model", "gpt-4o")]
182+
[McpMeta("version", "1.0")]
183183
public static string ToolWithMeta(string input)
184184
{
185185
return input;
@@ -192,7 +192,7 @@ public static string ToolWithoutMeta(string input)
192192
}
193193

194194
[McpServerTool]
195-
[McpMeta(Name = "test-key", Value = "test-value")]
195+
[McpMeta("test-key", "test-value")]
196196
public static string ToolWithSingleMeta(string input)
197197
{
198198
return input;
@@ -202,8 +202,8 @@ public static string ToolWithSingleMeta(string input)
202202
private class TestPromptClass
203203
{
204204
[McpServerPrompt]
205-
[McpMeta(Name = "type", Value = "reasoning")]
206-
[McpMeta(Name = "model", Value = "claude-3")]
205+
[McpMeta("type", "reasoning")]
206+
[McpMeta("model", "claude-3")]
207207
public static string PromptWithMeta(string input)
208208
{
209209
return input;
@@ -213,8 +213,8 @@ public static string PromptWithMeta(string input)
213213
private class TestResourceClass
214214
{
215215
[McpServerResource(UriTemplate = "resource://test/{id}")]
216-
[McpMeta(Name = "encoding", Value = "text/plain")]
217-
[McpMeta(Name = "caching", Value = "cached")]
216+
[McpMeta("encoding", "text/plain")]
217+
[McpMeta("caching", "cached")]
218218
public static string ResourceWithMeta(string id)
219219
{
220220
return $"Resource content for {id}";

0 commit comments

Comments
 (0)