Update content according to latest spec (#513)

* Update content according to latest spec

* Add Title to a bunch of types

* Add _meta to lots of types

* Address feedback, more cleanup, fix NAOT test failure
This commit is contained in:
Stephen Toub 2025-06-16 19:39:41 -04:00 • committed by GitHub
commit 2bcff315f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1700 additions and 853 deletions

View file

@ -103,7 +103,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
{
var requestContent = GetRequestContext(args);
if (requestContent?.Server is { } server &&
requestContent?.Params?.Meta?.ProgressToken is { } progressToken)
requestContent?.Params?.ProgressToken is { } progressToken)
{
return new TokenProgress(server, progressToken);
}
@ -180,6 +180,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
Prompt prompt = new()
{
Name = options?.Name ?? function.Name,
Title = options?.Title,
Description = options?.Description ?? function.Description,
Arguments = args,
};
@ -194,6 +195,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
if (method.GetCustomAttribute<McpServerPromptAttribute>() is { } promptAttr)
{
newOptions.Name ??= promptAttr.Name;
newOptions.Title ??= promptAttr.Title;
}
if (method.GetCustomAttribute<DescriptionAttribute>() is { } descAttr)
@ -248,7 +250,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
string text => new()
{
Description = ProtocolPrompt.Description,
Messages = [new() { Role = Role.User, Content = new() { Text = text, Type = "text" } }],
Messages = [new() { Role = Role.User, Content = new TextContentBlock { Text = text } }],
},
PromptMessage promptMessage => new()

View file

@ -110,7 +110,7 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
{
var requestContent = GetRequestContext(args);
if (requestContent?.Server is { } server &&
requestContent?.Params?.Meta?.ProgressToken is { } progressToken)
requestContent?.Params?.ProgressToken is { } progressToken)
{
return new TokenProgress(server, progressToken);
}
@ -262,6 +262,7 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
{
UriTemplate = options?.UriTemplate ?? DeriveUriTemplate(name, function),
Name = name,
Title = options?.Title,
Description = options?.Description,
MimeType = options?.MimeType,
};
@ -277,6 +278,7 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
{
newOptions.UriTemplate ??= resourceAttr.UriTemplate;
newOptions.Name ??= resourceAttr.Name;
newOptions.Title ??= resourceAttr.Title;
newOptions.MimeType ??= resourceAttr.MimeType;
}
@ -396,17 +398,17 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
TextContent tc => new()
{
Contents = [new TextResourceContents() { Uri = request.Params!.Uri, MimeType = ProtocolResourceTemplate.MimeType, Text = tc.Text }],
Contents = [new TextResourceContents { Uri = request.Params!.Uri, MimeType = ProtocolResourceTemplate.MimeType, Text = tc.Text }],
},
DataContent dc => new()
{
Contents = [new BlobResourceContents() { Uri = request.Params!.Uri, MimeType = dc.MediaType, Blob = dc.Base64Data.ToString() }],
Contents = [new BlobResourceContents { Uri = request.Params!.Uri, MimeType = dc.MediaType, Blob = dc.Base64Data.ToString() }],
},
string text => new()
{
Contents = [new TextResourceContents() { Uri = request.Params!.Uri, MimeType = ProtocolResourceTemplate.MimeType, Text = text }],
Contents = [new TextResourceContents { Uri = request.Params!.Uri, MimeType = ProtocolResourceTemplate.MimeType, Text = text }],
},
IEnumerable<ResourceContents> contents => new()

View file

@ -118,7 +118,7 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
{
var requestContent = GetRequestContext(args);
if (requestContent?.Server is { } server &&
requestContent?.Params?.Meta?.ProgressToken is { } progressToken)
requestContent?.Params?.ProgressToken is { } progressToken)
{
return new TokenProgress(server, progressToken);
}
@ -190,13 +190,15 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
options.OpenWorld is not null ||
options.ReadOnly is not null)
{
tool.Title = options.Title;
tool.Annotations = new()
{
Title = options?.Title,
IdempotentHint = options?.Idempotent,
DestructiveHint = options?.Destructive,
OpenWorldHint = options?.OpenWorld,
ReadOnlyHint = options?.ReadOnly,
Title = options.Title,
IdempotentHint = options.Idempotent,
DestructiveHint = options.Destructive,
OpenWorldHint = options.OpenWorld,
ReadOnlyHint = options.ReadOnly,
};
}
}
@ -260,7 +262,7 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
public override Tool ProtocolTool { get; }
/// <inheritdoc />
public override async ValueTask<CallToolResponse> InvokeAsync(
public override async ValueTask<CallToolResult> InvokeAsync(
RequestContext<CallToolRequestParams> request, CancellationToken cancellationToken = default)
{
Throw.IfNull(request);
@ -297,7 +299,7 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
return new()
{
IsError = true,
Content = [new() { Text = errorMessage, Type = "text" }],
Content = [new TextContentBlock { Text = errorMessage }],
};
}
@ -319,11 +321,11 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
string text => new()
{
Content = [new() { Text = text, Type = "text" }],
Content = [new TextContentBlock { Text = text }],
StructuredContent = structuredContent,
},
Content content => new()
ContentBlock content => new()
{
Content = [content],
StructuredContent = structuredContent,
@ -331,27 +333,23 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
IEnumerable<string> texts => new()
{
Content = [.. texts.Select(x => new Content() { Type = "text", Text = x ?? string.Empty })],
Content = [.. texts.Select(x => new TextContentBlock { Text = x ?? string.Empty })],
StructuredContent = structuredContent,
},
IEnumerable<AIContent> contentItems => ConvertAIContentEnumerableToCallToolResponse(contentItems, structuredContent),
IEnumerable<AIContent> contentItems => ConvertAIContentEnumerableToCallToolResult(contentItems, structuredContent),
IEnumerable<Content> contents => new()
IEnumerable<ContentBlock> contents => new()
{
Content = [.. contents],
StructuredContent = structuredContent,
},
CallToolResponse callToolResponse => callToolResponse,
CallToolResult callToolResponse => callToolResponse,
_ => new()
{
Content = [new()
{
Text = JsonSerializer.Serialize(result, AIFunction.JsonSerializerOptions.GetTypeInfo(typeof(object))),
Type = "text"
}],
Content = [new TextContentBlock { Text = JsonSerializer.Serialize(result, AIFunction.JsonSerializerOptions.GetTypeInfo(typeof(object))) }],
StructuredContent = structuredContent,
},
};
@ -434,9 +432,9 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
return nodeResult;
}
private static CallToolResponse ConvertAIContentEnumerableToCallToolResponse(IEnumerable<AIContent> contentItems, JsonNode? structuredContent)
private static CallToolResult ConvertAIContentEnumerableToCallToolResult(IEnumerable<AIContent> contentItems, JsonNode? structuredContent)
{
List<Content> contentList = [];
List<ContentBlock> contentList = [];
bool allErrorContent = true;
bool hasAny = false;

View file

@ -23,7 +23,7 @@ public abstract class DelegatingMcpServerTool : McpServerTool
public override Tool ProtocolTool => _innerTool.ProtocolTool;
/// <inheritdoc />
public override ValueTask<CallToolResponse> InvokeAsync(
public override ValueTask<CallToolResult> InvokeAsync(
RequestContext<CallToolRequestParams> request,
CancellationToken cancellationToken = default) =>
_innerTool.InvokeAsync(request, cancellationToken);

View file

@ -242,7 +242,13 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
if (request.Params?.Cursor is null)
{
result.Resources.AddRange(resources.Select(t => t.ProtocolResource).OfType<Resource>());
foreach (var r in resources)
{
if (r.ProtocolResource is { } resource)
{
result.Resources.Add(resource);
}
}
}
return result;
@ -257,7 +263,13 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
if (request.Params?.Cursor is null)
{
result.ResourceTemplates.AddRange(resources.Where(t => t.IsTemplated).Select(t => t.ProtocolResourceTemplate));
foreach (var rt in resources)
{
if (rt.IsTemplated)
{
result.ResourceTemplates.Add(rt.ProtocolResourceTemplate);
}
}
}
return result;
@ -366,7 +378,10 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
if (request.Params?.Cursor is null)
{
result.Prompts.AddRange(prompts.Select(t => t.ProtocolPrompt));
foreach (var p in prompts)
{
result.Prompts.Add(p.ProtocolPrompt);
}
}
return result;
@ -431,7 +446,10 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
if (request.Params?.Cursor is null)
{
result.Tools.AddRange(tools.Select(t => t.ProtocolTool));
foreach (var t in tools)
{
result.Tools.Add(t.ProtocolTool);
}
}
return result;
@ -467,7 +485,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
RequestMethods.ToolsCall,
callToolHandler,
McpJsonUtilities.JsonContext.Default.CallToolRequestParams,
McpJsonUtilities.JsonContext.Default.CallToolResponse);
McpJsonUtilities.JsonContext.Default.CallToolResult);
}
private void ConfigureLogging(McpServerOptions options)

View file

@ -94,11 +94,7 @@ public static class McpServerExtensions
samplingMessages.Add(new()
{
Role = role,
Content = new()
{
Type = "text",
Text = textContent.Text,
},
Content = new TextContentBlock { Text = textContent.Text },
});
break;
@ -106,12 +102,17 @@ public static class McpServerExtensions
samplingMessages.Add(new()
{
Role = role,
Content = new()
{
Type = dataContent.HasTopLevelMediaType("image") ? "image" : "audio",
MimeType = dataContent.MediaType,
Data = dataContent.Base64Data.ToString(),
},
Content = dataContent.HasTopLevelMediaType("image") ?
new ImageContentBlock()
{
MimeType = dataContent.MediaType,
Data = dataContent.Base64Data.ToString(),
} :
new AudioContentBlock()
{
MimeType = dataContent.MediaType,
Data = dataContent.Base64Data.ToString(),
},
});
break;
}
@ -135,7 +136,9 @@ public static class McpServerExtensions
ModelPreferences = modelPreferences,
}, cancellationToken).ConfigureAwait(false);
return new(new ChatMessage(result.Role is Role.User ? ChatRole.User : ChatRole.Assistant, [result.Content.ToAIContent()]))
AIContent? responseContent = result.Content.ToAIContent();
return new(new ChatMessage(result.Role is Role.User ? ChatRole.User : ChatRole.Assistant, responseContent is not null ? [responseContent] : []))
{
ModelId = result.Model,
FinishReason = result.StopReason switch

View file

@ -5,7 +5,7 @@ namespace ModelContextProtocol.Server;
/// <summary>
/// Provides configuration options for the MCP server.
/// </summary>
public class McpServerOptions
public sealed class McpServerOptions
{
/// <summary>
/// Gets or sets information about this server implementation, including its name and version.

View file

@ -34,7 +34,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>.
/// </description>
/// </item>

View file

@ -25,7 +25,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>.
/// </description>
/// </item>
@ -117,4 +117,7 @@ public sealed class McpServerPromptAttribute : Attribute
/// <summary>Gets the name of the prompt.</summary>
/// <remarks>If <see langword="null"/>, the method name will be used.</remarks>
public string? Name { get; set; }
/// <summary>Gets or sets the title of the prompt.</summary>
public string? Title { get; set; }
}

View file

@ -38,6 +38,11 @@ public sealed class McpServerPromptCreateOptions
/// </remarks>
public string? Name { get; set; }
/// <summary>
/// Gets or sets the title to use for the <see cref="McpServerPrompt"/>.
/// </summary>
public string? Title { get; set; }
/// <summary>
/// Gets or set the description to use for the <see cref="McpServerPrompt"/>.
/// </summary>
@ -71,6 +76,7 @@ public sealed class McpServerPromptCreateOptions
{
Services = Services,
Name = Name,
Title = Title,
Description = Description,
SerializerOptions = SerializerOptions,
SchemaCreateOptions = SchemaCreateOptions,

View file

@ -1,5 +1,3 @@
using Microsoft.Extensions.DependencyInjection;
namespace ModelContextProtocol.Server;
/// <summary>

View file

@ -35,7 +35,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>.
/// </description>
/// </item>
@ -90,7 +90,7 @@ namespace ModelContextProtocol.Server;
/// <description>Wrapped in a list containing the single <see cref="ResourceContents"/>.</description>
/// </item>
/// <item>
/// <term><see cref="TextContent"/></term>
/// <term><see cref="TextContentBlock"/></term>
/// <description>Converted to a list containing a single <see cref="TextResourceContents"/>.</description>
/// </item>
/// <item>
@ -107,7 +107,7 @@ namespace ModelContextProtocol.Server;
/// </item>
/// <item>
/// <term><see cref="IEnumerable{AIContent}"/> of <see cref="AIContent"/></term>
/// <description>Converted to a list containing a <see cref="TextResourceContents"/> for each <see cref="TextContent"/> and a <see cref="BlobResourceContents"/> for each <see cref="DataContent"/>.</description>
/// <description>Converted to a list containing a <see cref="TextResourceContents"/> for each <see cref="TextContentBlock"/> and a <see cref="BlobResourceContents"/> for each <see cref="DataContent"/>.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{String}"/> of <see cref="string"/></term>

View file

@ -23,7 +23,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>.
/// </description>
/// </item>
@ -78,7 +78,7 @@ namespace ModelContextProtocol.Server;
/// <description>Wrapped in a list containing the single <see cref="ResourceContents"/>.</description>
/// </item>
/// <item>
/// <term><see cref="TextContent"/></term>
/// <term><see cref="TextContentBlock"/></term>
/// <description>Converted to a list containing a single <see cref="TextResourceContents"/>.</description>
/// </item>
/// <item>
@ -95,7 +95,7 @@ namespace ModelContextProtocol.Server;
/// </item>
/// <item>
/// <term><see cref="IEnumerable{AIContent}"/> of <see cref="AIContent"/></term>
/// <description>Converted to a list containing a <see cref="TextResourceContents"/> for each <see cref="TextContent"/> and a <see cref="BlobResourceContents"/> for each <see cref="DataContent"/>.</description>
/// <description>Converted to a list containing a <see cref="TextResourceContents"/> for each <see cref="TextContentBlock"/> and a <see cref="BlobResourceContents"/> for each <see cref="DataContent"/>.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{String}"/> of <see cref="string"/></term>
@ -130,6 +130,9 @@ public sealed class McpServerResourceAttribute : Attribute
/// <remarks>If <see langword="null"/>, the method name will be used.</remarks>
public string? Name { get; set; }
/// <summary>Gets or sets the title of the resource.</summary>
public string? Title { get; set; }
/// <summary>Gets or sets the MIME (media) type of the resource.</summary>
public string? MimeType { get; set; }
}

View file

@ -48,6 +48,11 @@ public sealed class McpServerResourceCreateOptions
/// </remarks>
public string? Name { get; set; }
/// <summary>
/// Gets or sets the title to use for the <see cref="McpServerPrompt"/>.
/// </summary>
public string? Title { get; set; }
/// <summary>
/// Gets or set the description to use for the <see cref="McpServerResource"/>.
/// </summary>
@ -87,6 +92,7 @@ public sealed class McpServerResourceCreateOptions
Services = Services,
UriTemplate = UriTemplate,
Name = Name,
Title = Title,
Description = Description,
MimeType = MimeType,
SerializerOptions = SerializerOptions,

View file

@ -1,5 +1,3 @@
using Microsoft.Extensions.DependencyInjection;
namespace ModelContextProtocol.Server;
/// <summary>

View file

@ -24,7 +24,7 @@ namespace ModelContextProtocol.Server;
/// <see cref="MethodInfo"/>, and are what are used implicitly by WithToolsFromAssembly and WithTools. The <see cref="M:McpServerTool.Create"/> methods
/// create <see cref="McpServerTool"/> instances capable of working with a large variety of .NET method signatures, automatically handling
/// how parameters are marshaled into the method from the JSON received from the MCP client, and how the return value is marshaled back
/// into the <see cref="CallToolResponse"/> that's then serialized and sent back to the client.
/// into the <see cref="CallToolResult"/> that's then serialized and sent back to the client.
/// </para>
/// <para>
/// By default, parameters are sourced from the <see cref="CallToolRequestParams.Arguments"/> dictionary, which is a collection
@ -35,7 +35,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>. The parameter is not included in the generated JSON schema.
/// </description>
/// </item>
@ -90,44 +90,44 @@ namespace ModelContextProtocol.Server;
/// to provide data to the method.
/// </para>
/// <para>
/// Return values from a method are used to create the <see cref="CallToolResponse"/> that is sent back to the client:
/// Return values from a method are used to create the <see cref="CallToolResult"/> that is sent back to the client:
/// </para>
/// <list type="table">
/// <item>
/// <term><see langword="null"/></term>
/// <description>Returns an empty <see cref="CallToolResponse.Content"/> list.</description>
/// <description>Returns an empty <see cref="CallToolResult.Content"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="AIContent"/></term>
/// <description>Converted to a single <see cref="Content"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// <description>Converted to a single <see cref="ContentBlock"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// </item>
/// <item>
/// <term><see cref="string"/></term>
/// <description>Converted to a single <see cref="Content"/> object with <see cref="Content.Text"/> set to the string value and <see cref="Content.Type"/> set to "text".</description>
/// <description>Converted to a single <see cref="TextContentBlock"/> object with its text set to the string value.</description>
/// </item>
/// <item>
/// <term><see cref="Content"/></term>
/// <description>Returned as a single-item <see cref="Content"/> list.</description>
/// <term><see cref="ContentBlock"/></term>
/// <description>Returned as a single-item <see cref="ContentBlock"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{String}"/> of <see cref="string"/></term>
/// <description>Each <see cref="string"/> is converted to a <see cref="Content"/> object with <see cref="Content.Text"/> set to the string value and <see cref="Content.Type"/> set to "text".</description>
/// <description>Each <see cref="string"/> is converted to a <see cref="TextContentBlock"/> object with its text set to the string value.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{AIContent}"/> of <see cref="AIContent"/></term>
/// <description>Each <see cref="AIContent"/> is converted to a <see cref="Content"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// <description>Each <see cref="AIContent"/> is converted to a <see cref="ContentBlock"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{Content}"/> of <see cref="Content"/></term>
/// <description>Returned as the <see cref="Content"/> list.</description>
/// <term><see cref="IEnumerable{ContentBlock}"/> of <see cref="ContentBlock"/></term>
/// <description>Returned as the <see cref="ContentBlock"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="CallToolResponse"/></term>
/// <term><see cref="CallToolResult"/></term>
/// <description>Returned directly without modification.</description>
/// </item>
/// <item>
/// <term>Other types</term>
/// <description>Serialized to JSON and returned as a single <see cref="Content"/> object with <see cref="Content.Type"/> set to "text".</description>
/// <description>Serialized to JSON and returned as a single <see cref="ContentBlock"/> object with <see cref="ContentBlock.Type"/> set to "text".</description>
/// </item>
/// </list>
/// </remarks>
@ -146,7 +146,7 @@ public abstract class McpServerTool : IMcpServerPrimitive
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>The call response from invoking the tool.</returns>
/// <exception cref="ArgumentNullException"><paramref name="request"/> is <see langword="null"/>.</exception>
public abstract ValueTask<CallToolResponse> InvokeAsync(
public abstract ValueTask<CallToolResult> InvokeAsync(
RequestContext<CallToolRequestParams> request,
CancellationToken cancellationToken = default);

View file

@ -26,7 +26,7 @@ namespace ModelContextProtocol.Server;
/// <item>
/// <description>
/// <see cref="CancellationToken"/> parameters are automatically bound to a <see cref="CancellationToken"/> provided by the
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotification"/>s sent by the client for this operation's
/// <see cref="IMcpServer"/> and that respects any <see cref="CancelledNotificationParams"/>s sent by the client for this operation's
/// <see cref="RequestId"/>. The parameter is not included in the generated JSON schema.
/// </description>
/// </item>
@ -81,44 +81,44 @@ namespace ModelContextProtocol.Server;
/// to provide data to the method.
/// </para>
/// <para>
/// Return values from a method are used to create the <see cref="CallToolResponse"/> that is sent back to the client:
/// Return values from a method are used to create the <see cref="CallToolResult"/> that is sent back to the client:
/// </para>
/// <list type="table">
/// <item>
/// <term><see langword="null"/></term>
/// <description>Returns an empty <see cref="CallToolResponse.Content"/> list.</description>
/// <description>Returns an empty <see cref="CallToolResult.Content"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="AIContent"/></term>
/// <description>Converted to a single <see cref="Content"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// <description>Converted to a single <see cref="ContentBlock"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// </item>
/// <item>
/// <term><see cref="string"/></term>
/// <description>Converted to a single <see cref="Content"/> object with <see cref="Content.Text"/> set to the string value and <see cref="Content.Type"/> set to "text".</description>
/// <description>Converted to a single <see cref="TextContentBlock"/> object with its text set to the string value.</description>
/// </item>
/// <item>
/// <term><see cref="Content"/></term>
/// <description>Returned as a single-item <see cref="Content"/> list.</description>
/// <term><see cref="ContentBlock"/></term>
/// <description>Returned as a single-item <see cref="ContentBlock"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{String}"/> of <see cref="string"/></term>
/// <description>Each <see cref="string"/> is converted to a <see cref="Content"/> object with <see cref="Content.Text"/> set to the string value and <see cref="Content.Type"/> set to "text".</description>
/// <description>Each <see cref="string"/> is converted to a <see cref="ContentBlock"/> object with its text set to the string value.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{AIContent}"/> of <see cref="AIContent"/></term>
/// <description>Each <see cref="AIContent"/> is converted to a <see cref="Content"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// <description>Each <see cref="AIContent"/> is converted to a <see cref="ContentBlock"/> object using <see cref="AIContentExtensions.ToContent(AIContent)"/>.</description>
/// </item>
/// <item>
/// <term><see cref="IEnumerable{Content}"/> of <see cref="Content"/></term>
/// <description>Returned as the <see cref="Content"/> list.</description>
/// <term><see cref="IEnumerable{Content}"/> of <see cref="ContentBlock"/></term>
/// <description>Returned as the <see cref="ContentBlock"/> list.</description>
/// </item>
/// <item>
/// <term><see cref="CallToolResponse"/></term>
/// <term><see cref="CallToolResult"/></term>
/// <description>Returned directly without modification.</description>
/// </item>
/// <item>
/// <term>Other types</term>
/// <description>Serialized to JSON and returned as a single <see cref="Content"/> object with <see cref="Content.Type"/> set to "text".</description>
/// <description>Serialized to JSON and returned as a single <see cref="ContentBlock"/> object with <see cref="ContentBlock.Type"/> set to "text".</description>
/// </item>
/// </list>
/// </remarks>
@ -246,7 +246,7 @@ public sealed class McpServerToolAttribute : Attribute
/// </summary>
/// <remarks>
/// When enabled, the tool will attempt to populate the <see cref="Tool.OutputSchema"/>
/// and provide structured content in the <see cref="CallToolResponse.StructuredContent"/> property.
/// and provide structured content in the <see cref="CallToolResult.StructuredContent"/> property.
/// </remarks>
public bool UseStructuredContent { get; set; }
}

View file

@ -130,7 +130,7 @@ public sealed class McpServerToolCreateOptions
/// </summary>
/// <remarks>
/// When enabled, the tool will attempt to populate the <see cref="Tool.OutputSchema"/>
/// and provide structured content in the <see cref="CallToolResponse.StructuredContent"/> property.
/// and provide structured content in the <see cref="CallToolResult.StructuredContent"/> property.
/// </remarks>
public bool UseStructuredContent { get; set; }

View file

@ -1,5 +1,3 @@
using Microsoft.Extensions.DependencyInjection;
namespace ModelContextProtocol.Server;
/// <summary>

View file

@ -1,5 +1,3 @@
using Microsoft.Extensions.DependencyInjection;
namespace ModelContextProtocol.Server;
/// <summary>