Skip to content

Commit 62e92fa

Browse files
authored
Add ToolAnnotations support (#124)
* Add ToolAnnotations support * Address feedback
1 parent 2c1672c commit 62e92fa

File tree

70 files changed

+645
-394
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+645
-394
lines changed

samples/AspNetCoreSseServer/Tools/SampleLlmTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace TestServerWithHosting.Tools;
1010
[McpServerToolType]
1111
public static class SampleLlmTool
1212
{
13-
[McpServerTool("sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
13+
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
1414
public static async Task<string> SampleLLM(
1515
IMcpServer thisServer,
1616
[Description("The prompt to send to the LLM")] string prompt,

samples/TestServerWithHosting/Tools/SampleLlmTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace TestServerWithHosting.Tools;
1010
[McpServerToolType]
1111
public static class SampleLlmTool
1212
{
13-
[McpServerTool("sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
13+
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
1414
public static async Task<string> SampleLLM(
1515
IMcpServer thisServer,
1616
[Description("The prompt to send to the LLM")] string prompt,

src/ModelContextProtocol/AIContentExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static AIContent ToAIContent(this Content content)
3333
Throw.IfNull(content);
3434

3535
AIContent ac;
36-
if (content is { Type: "image", MimeType: not null, Data: not null })
36+
if (content is { Type: "image" or "audio", MimeType: not null, Data: not null })
3737
{
3838
ac = new DataContent(Convert.FromBase64String(content.Data), content.MimeType);
3939
}
@@ -112,6 +112,7 @@ internal static Content ToContent(this AIContent content) =>
112112
Text = textContent.Text,
113113
Type = "text",
114114
},
115+
115116
DataContent dataContent => new()
116117
{
117118
Data = dataContent.GetBase64Data(),
@@ -121,6 +122,7 @@ internal static Content ToContent(this AIContent content) =>
121122
dataContent.HasTopLevelMediaType("audio") ? "audio" :
122123
"resource",
123124
},
125+
124126
_ => new()
125127
{
126128
Text = JsonSerializer.Serialize(content, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object))),

src/ModelContextProtocol/Client/McpClientExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ internal static (IList<ChatMessage> Messages, ChatOptions? Options) ToChatClient
469469
{
470470
message.Contents.Add(new TextContent(sm.Content.Text));
471471
}
472-
else if (sm.Content is { Type: "image", MimeType: not null, Data: not null })
472+
else if (sm.Content is { Type: "image" or "audio", MimeType: not null, Data: not null })
473473
{
474474
message.Contents.Add(new DataContent(Convert.FromBase64String(sm.Content.Data), sm.Content.MimeType));
475475
}
@@ -512,11 +512,11 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat
512512
{
513513
foreach (var lmc in lastMessage.Contents)
514514
{
515-
if (lmc is DataContent dc && dc.HasTopLevelMediaType("image"))
515+
if (lmc is DataContent dc && (dc.HasTopLevelMediaType("image") || dc.HasTopLevelMediaType("audio")))
516516
{
517517
content = new()
518518
{
519-
Type = "image",
519+
Type = dc.HasTopLevelMediaType("image") ? "image" : "audio",
520520
MimeType = dc.MediaType,
521521
Data = dc.GetBase64Data(),
522522
};

src/ModelContextProtocol/Client/McpClientTool.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,24 @@ namespace ModelContextProtocol.Client;
99
public sealed class McpClientTool : AIFunction
1010
{
1111
private readonly IMcpClient _client;
12-
private readonly Tool _tool;
1312

1413
internal McpClientTool(IMcpClient client, Tool tool)
1514
{
1615
_client = client;
17-
_tool = tool;
16+
ProtocolTool = tool;
1817
}
1918

19+
/// <summary>Gets the protocol <see cref="Tool"/> type for this instance.</summary>
20+
public Tool ProtocolTool { get; }
21+
2022
/// <inheritdoc/>
21-
public override string Name => _tool.Name;
23+
public override string Name => ProtocolTool.Name;
2224

2325
/// <inheritdoc/>
24-
public override string Description => _tool.Description ?? string.Empty;
26+
public override string Description => ProtocolTool.Description ?? string.Empty;
2527

2628
/// <inheritdoc/>
27-
public override JsonElement JsonSchema => _tool.InputSchema;
29+
public override JsonElement JsonSchema => ProtocolTool.InputSchema;
2830

2931
/// <inheritdoc/>
3032
public override JsonSerializerOptions JsonSerializerOptions => McpJsonUtilities.DefaultOptions;
@@ -37,7 +39,7 @@ internal McpClientTool(IMcpClient client, Tool tool)
3739
arguments as IReadOnlyDictionary<string, object?> ??
3840
arguments.ToDictionary();
3941

40-
CallToolResponse result = await _client.CallToolAsync(_tool.Name, argDict, cancellationToken).ConfigureAwait(false);
42+
CallToolResponse result = await _client.CallToolAsync(ProtocolTool.Name, argDict, cancellationToken).ConfigureAwait(false);
4143
return JsonSerializer.SerializeToElement(result, McpJsonUtilities.JsonContext.Default.CallToolResponse);
4244
}
4345
}

src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.Tools.cs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,9 @@ public static partial class McpServerBuilderExtensions
3737
{
3838
if (toolMethod.GetCustomAttribute<McpServerToolAttribute>() is not null)
3939
{
40-
if (toolMethod.IsStatic)
41-
{
42-
builder.Services.AddSingleton(services => McpServerTool.Create(toolMethod, services: services));
43-
}
44-
else
45-
{
46-
builder.Services.AddSingleton(services => McpServerTool.Create(toolMethod, typeof(TTool), services: services));
47-
}
40+
builder.Services.AddSingleton((Func<IServiceProvider, McpServerTool>)(toolMethod.IsStatic ?
41+
services => McpServerTool.Create(toolMethod, new McpServerToolCreateOptions() { Services = services }) :
42+
services => McpServerTool.Create(toolMethod, typeof(TTool), new() { Services = services })));
4843
}
4944
}
5045

@@ -71,18 +66,13 @@ public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, params
7166
{
7267
if (toolType is not null)
7368
{
74-
foreach (var method in toolType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
69+
foreach (var toolMethod in toolType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
7570
{
76-
if (method.GetCustomAttribute<McpServerToolAttribute>() is not null)
71+
if (toolMethod.GetCustomAttribute<McpServerToolAttribute>() is not null)
7772
{
78-
if (method.IsStatic)
79-
{
80-
builder.Services.AddSingleton(services => McpServerTool.Create(method, services: services));
81-
}
82-
else
83-
{
84-
builder.Services.AddSingleton(services => McpServerTool.Create(method, toolType, services: services));
85-
}
73+
builder.Services.AddSingleton((Func<IServiceProvider, McpServerTool>)(toolMethod.IsStatic ?
74+
services => McpServerTool.Create(toolMethod, new McpServerToolCreateOptions() { Services = services }) :
75+
services => McpServerTool.Create(toolMethod, toolType, new() { Services = services })));
8676
}
8777
}
8878
}

src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public sealed class StdioServerTransport : TransportBase, IServerTransport
2525
private readonly TextReader _stdInReader;
2626
private readonly Stream _stdOutStream;
2727

28-
private SemaphoreSlim _sendLock = new(1, 1);
28+
private readonly SemaphoreSlim _sendLock = new(1, 1);
2929
private Task? _readTask;
3030
private CancellationTokenSource? _shutdownCts;
3131

src/ModelContextProtocol/Protocol/Types/Annotated.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace ModelContextProtocol.Protocol.Types;
44

55
/// <summary>
66
/// Base for objects that include optional annotations for the client. The client can use annotations to inform how objects are used or displayed.
7-
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
7+
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
88
/// </summary>
99
public abstract record Annotated
1010
{

src/ModelContextProtocol/Protocol/Types/Annotations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace ModelContextProtocol.Protocol.Types;
44

55
/// <summary>
66
/// Represents annotations that can be attached to content.
7-
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
7+
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
88
/// </summary>
99
public record Annotations
1010
{

src/ModelContextProtocol/Protocol/Types/Argument.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace ModelContextProtocol.Protocol.Types;
44

55
/// <summary>
66
/// Used for completion requests to provide additional context for the completion options.
7-
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json">See the schema for details</see>
7+
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
88
/// </summary>
99
public class Argument
1010
{

0 commit comments

Comments
 (0)