Skip to content

Commit 33e438e

Browse files
committed
Add _meta to lots of types
1 parent e9caa71 commit 33e438e

Some content is hidden

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

52 files changed

+399
-105
lines changed

samples/EverythingServer/Tools/LongRunningTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static async Task<string> LongRunningOperation(
1515
int duration = 10,
1616
int steps = 5)
1717
{
18-
var progressToken = context.Params?.Meta?.ProgressToken;
18+
var progressToken = context.Params?.ProgressToken;
1919
var stepDuration = duration / steps;
2020

2121
for (int i = 1; i <= steps + 1; i++)

src/ModelContextProtocol.Core/Client/McpClient.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public McpClient(IClientTransport clientTransport, McpClientOptions? options, IL
5757
RequestMethods.SamplingCreateMessage,
5858
(request, _, cancellationToken) => samplingHandler(
5959
request,
60-
request?.Meta?.ProgressToken is { } token ? new TokenProgress(this, token) : NullProgress.Instance,
60+
request?.ProgressToken is { } token ? new TokenProgress(this, token) : NullProgress.Instance,
6161
cancellationToken),
6262
McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams,
6363
McpJsonUtilities.JsonContext.Default.CreateMessageResult);
@@ -179,9 +179,12 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
179179
}
180180

181181
// Send initialized notification
182-
await SendMessageAsync(
183-
new JsonRpcNotification { Method = NotificationMethods.InitializedNotification },
184-
initializationCts.Token).ConfigureAwait(false);
182+
await this.SendNotificationAsync(
183+
NotificationMethods.InitializedNotification,
184+
new InitializedNotificationParams(),
185+
McpJsonUtilities.JsonContext.Default.InitializedNotificationParams,
186+
cancellationToken: initializationCts.Token).ConfigureAwait(false);
187+
185188
}
186189
catch (OperationCanceledException oce) when (initializationCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
187190
{

src/ModelContextProtocol.Core/Client/McpClientExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ static async ValueTask<CallToolResult> SendRequestWithProgressAsync(
866866
await using var _ = client.RegisterNotificationHandler(NotificationMethods.ProgressNotification,
867867
(notification, cancellationToken) =>
868868
{
869-
if (JsonSerializer.Deserialize(notification.Params, McpJsonUtilities.JsonContext.Default.ProgressNotification) is { } pn &&
869+
if (JsonSerializer.Deserialize(notification.Params, McpJsonUtilities.JsonContext.Default.ProgressNotificationParams) is { } pn &&
870870
pn.ProgressToken == progressToken)
871871
{
872872
progress.Report(pn.Progress);
@@ -881,7 +881,7 @@ static async ValueTask<CallToolResult> SendRequestWithProgressAsync(
881881
{
882882
Name = toolName,
883883
Arguments = ToArgumentsDictionary(arguments, serializerOptions),
884-
Meta = new() { ProgressToken = progressToken },
884+
ProgressToken = progressToken,
885885
},
886886
McpJsonUtilities.JsonContext.Default.CallToolRequestParams,
887887
McpJsonUtilities.JsonContext.Default.CallToolResult,
@@ -991,7 +991,7 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat
991991
Throw.IfNull(requestParams);
992992

993993
var (messages, options) = requestParams.ToChatClientArguments();
994-
var progressToken = requestParams.Meta?.ProgressToken;
994+
var progressToken = requestParams.ProgressToken;
995995

996996
List<ChatResponseUpdate> updates = [];
997997
await foreach (var update in chatClient.GetStreamingResponseAsync(messages, options, cancellationToken).ConfigureAwait(false))

src/ModelContextProtocol.Core/McpEndpointExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,12 @@ public static Task NotifyProgressAsync(
201201

202202
return endpoint.SendNotificationAsync(
203203
NotificationMethods.ProgressNotification,
204-
new ProgressNotification
204+
new ProgressNotificationParams
205205
{
206206
ProgressToken = progressToken,
207207
Progress = progress,
208208
},
209-
McpJsonUtilities.JsonContext.Default.ProgressNotification,
209+
McpJsonUtilities.JsonContext.Default.ProgressNotificationParams,
210210
cancellationToken);
211211
}
212212
}

src/ModelContextProtocol.Core/McpJsonUtilities.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,20 @@ internal static bool IsValidMcpToolSchema(JsonElement element)
9696
[JsonSerializable(typeof(JsonRpcResponse))]
9797
[JsonSerializable(typeof(JsonRpcError))]
9898

99+
// MCP Notification Params
100+
[JsonSerializable(typeof(CancelledNotificationParams))]
101+
[JsonSerializable(typeof(InitializedNotificationParams))]
102+
[JsonSerializable(typeof(LoggingMessageNotificationParams))]
103+
[JsonSerializable(typeof(ProgressNotificationParams))]
104+
[JsonSerializable(typeof(PromptListChangedNotificationParams))]
105+
[JsonSerializable(typeof(ResourceListChangedNotificationParams))]
106+
[JsonSerializable(typeof(ResourceUpdatedNotificationParams))]
107+
[JsonSerializable(typeof(RootsListChangedNotificationParams))]
108+
[JsonSerializable(typeof(ToolListChangedNotificationParams))]
109+
99110
// MCP Request Params / Results
100111
[JsonSerializable(typeof(CallToolRequestParams))]
101112
[JsonSerializable(typeof(CallToolResult))]
102-
[JsonSerializable(typeof(CancelledNotification))]
103113
[JsonSerializable(typeof(CompleteRequestParams))]
104114
[JsonSerializable(typeof(CompleteResult))]
105115
[JsonSerializable(typeof(CreateMessageRequestParams))]
@@ -121,16 +131,16 @@ internal static bool IsValidMcpToolSchema(JsonElement element)
121131
[JsonSerializable(typeof(ListRootsResult))]
122132
[JsonSerializable(typeof(ListToolsRequestParams))]
123133
[JsonSerializable(typeof(ListToolsResult))]
124-
[JsonSerializable(typeof(LoggingMessageNotificationParams))]
125134
[JsonSerializable(typeof(PingResult))]
126-
[JsonSerializable(typeof(ProgressNotification))]
127135
[JsonSerializable(typeof(ReadResourceRequestParams))]
128136
[JsonSerializable(typeof(ReadResourceResult))]
129-
[JsonSerializable(typeof(ResourceUpdatedNotificationParams))]
130137
[JsonSerializable(typeof(SetLevelRequestParams))]
131138
[JsonSerializable(typeof(SubscribeRequestParams))]
132139
[JsonSerializable(typeof(UnsubscribeRequestParams))]
140+
141+
// Other MCP Types
133142
[JsonSerializable(typeof(IReadOnlyDictionary<string, object>))]
143+
[JsonSerializable(typeof(ProgressToken))]
134144
[JsonSerializable(typeof(PromptMessage[]))]
135145

136146
// Primitive types for use in consuming AIFunctions

src/ModelContextProtocol.Core/McpSession.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ private async Task HandleNotification(JsonRpcNotification notification, Cancella
273273
{
274274
try
275275
{
276-
if (GetCancelledNotificationParams(notification.Params) is CancelledNotification cn &&
276+
if (GetCancelledNotificationParams(notification.Params) is CancelledNotificationParams cn &&
277277
_handlingRequests.TryGetValue(cn.RequestId, out var cts))
278278
{
279279
await cts.CancelAsync().ConfigureAwait(false);
@@ -337,7 +337,7 @@ private CancellationTokenRegistration RegisterCancellation(CancellationToken can
337337
_ = state.Item1.SendMessageAsync(new JsonRpcNotification
338338
{
339339
Method = NotificationMethods.CancelledNotification,
340-
Params = JsonSerializer.SerializeToNode(new CancelledNotification { RequestId = state.Item2.Id }, McpJsonUtilities.JsonContext.Default.CancelledNotification),
340+
Params = JsonSerializer.SerializeToNode(new CancelledNotificationParams { RequestId = state.Item2.Id }, McpJsonUtilities.JsonContext.Default.CancelledNotificationParams),
341341
RelatedTransport = state.Item2.RelatedTransport,
342342
});
343343
}, Tuple.Create(this, request));
@@ -495,7 +495,7 @@ public async Task SendMessageAsync(JsonRpcMessage message, CancellationToken can
495495
// server won't be sending a response, or per the specification, the response should be ignored. There are inherent
496496
// race conditions here, so it's possible and allowed for the operation to complete before we get to this point.
497497
if (message is JsonRpcNotification { Method: NotificationMethods.CancelledNotification } notification &&
498-
GetCancelledNotificationParams(notification.Params) is CancelledNotification cn &&
498+
GetCancelledNotificationParams(notification.Params) is CancelledNotificationParams cn &&
499499
_pendingRequests.TryRemove(cn.RequestId, out var tcs))
500500
{
501501
tcs.TrySetCanceled(default);
@@ -518,11 +518,11 @@ public async Task SendMessageAsync(JsonRpcMessage message, CancellationToken can
518518
private Task SendToRelatedTransportAsync(JsonRpcMessage message, CancellationToken cancellationToken)
519519
=> (message.RelatedTransport ?? _transport).SendMessageAsync(message, cancellationToken);
520520

521-
private static CancelledNotification? GetCancelledNotificationParams(JsonNode? notificationParams)
521+
private static CancelledNotificationParams? GetCancelledNotificationParams(JsonNode? notificationParams)
522522
{
523523
try
524524
{
525-
return JsonSerializer.Deserialize(notificationParams, McpJsonUtilities.JsonContext.Default.CancelledNotification);
525+
return JsonSerializer.Deserialize(notificationParams, McpJsonUtilities.JsonContext.Default.CancelledNotificationParams);
526526
}
527527
catch
528528
{

src/ModelContextProtocol.Core/Protocol/CallToolResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace ModelContextProtocol.Protocol;
2020
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
2121
/// </para>
2222
/// </remarks>
23-
public class CallToolResult
23+
public class CallToolResult : Result
2424
{
2525
/// <summary>
2626
/// Gets or sets the response content from the tool call.

src/ModelContextProtocol.Core/Protocol/CancelledNotification.cs renamed to src/ModelContextProtocol.Core/Protocol/CancelledNotificationParams.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace ModelContextProtocol.Protocol;
1111
/// method identifier. When a client sends this notification, the server should attempt to
1212
/// cancel any ongoing operations associated with the specified request ID.
1313
/// </remarks>
14-
public sealed class CancelledNotification
14+
public sealed class CancelledNotificationParams : NotificationParams
1515
{
1616
/// <summary>
1717
/// Gets or sets the ID of the request to cancel.

src/ModelContextProtocol.Core/Protocol/CompleteResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace ModelContextProtocol.Protocol;
2323
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
2424
/// </para>
2525
/// </remarks>
26-
public class CompleteResult
26+
public class CompleteResult : Result
2727
{
2828
/// <summary>
2929
/// Gets or sets the completion object containing the suggested values and pagination information.

src/ModelContextProtocol.Core/Protocol/ContentBlock.cs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using Microsoft.Extensions.AI;
12
using System.ComponentModel;
23
using System.Diagnostics;
34
using System.Text.Json;
5+
using System.Text.Json.Nodes;
46
using System.Text.Json.Serialization;
57

68
namespace ModelContextProtocol.Protocol;
@@ -78,6 +80,7 @@ public class Converter : JsonConverter<ContentBlock>
7880
long? size = null;
7981
ResourceContents? resource = null;
8082
Annotations? annotations = null;
83+
JsonObject? meta = null;
8184

8285
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
8386
{
@@ -128,6 +131,10 @@ public class Converter : JsonConverter<ContentBlock>
128131
annotations = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.Annotations);
129132
break;
130133

134+
case "_meta":
135+
meta = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.JsonObject);
136+
break;
137+
131138
default:
132139
break;
133140
}
@@ -140,6 +147,7 @@ public class Converter : JsonConverter<ContentBlock>
140147
{
141148
Text = text ?? throw new JsonException("Text contents must be provided for 'text' type."),
142149
Annotations = annotations,
150+
Meta = meta,
143151
};
144152

145153
case "image":
@@ -148,6 +156,7 @@ public class Converter : JsonConverter<ContentBlock>
148156
Data = data ?? throw new JsonException("Image data must be provided for 'image' type."),
149157
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'image' type."),
150158
Annotations = annotations,
159+
Meta = meta,
151160
};
152161

153162
case "audio":
@@ -156,13 +165,15 @@ public class Converter : JsonConverter<ContentBlock>
156165
Data = data ?? throw new JsonException("Audio data must be provided for 'audio' type."),
157166
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'audio' type."),
158167
Annotations = annotations,
168+
Meta = meta,
159169
};
160170

161171
case "resource":
162172
return new EmbeddedResourceBlock()
163173
{
164174
Resource = resource ?? throw new JsonException("Resource contents must be provided for 'resource' type."),
165-
Annotations = annotations
175+
Annotations = annotations,
176+
Meta = meta,
166177
};
167178

168179
case "resource_link":
@@ -198,21 +209,41 @@ public override void Write(Utf8JsonWriter writer, ContentBlock value, JsonSerial
198209
{
199210
case TextContentBlock textContent:
200211
writer.WriteString("text", textContent.Text);
212+
if (textContent.Meta is not null)
213+
{
214+
writer.WritePropertyName("_meta");
215+
JsonSerializer.Serialize(writer, textContent.Meta, McpJsonUtilities.JsonContext.Default.JsonObject);
216+
}
201217
break;
202218

203219
case ImageContentBlock imageContent:
204220
writer.WriteString("data", imageContent.Data);
205221
writer.WriteString("mimeType", imageContent.MimeType);
222+
if (imageContent.Meta is not null)
223+
{
224+
writer.WritePropertyName("_meta");
225+
JsonSerializer.Serialize(writer, imageContent.Meta, McpJsonUtilities.JsonContext.Default.JsonObject);
226+
}
206227
break;
207228

208229
case AudioContentBlock audioContent:
209230
writer.WriteString("data", audioContent.Data);
210231
writer.WriteString("mimeType", audioContent.MimeType);
232+
if (audioContent.Meta is not null)
233+
{
234+
writer.WritePropertyName("_meta");
235+
JsonSerializer.Serialize(writer, audioContent.Meta, McpJsonUtilities.JsonContext.Default.JsonObject);
236+
}
211237
break;
212238

213239
case EmbeddedResourceBlock embeddedResource:
214240
writer.WritePropertyName("resource");
215241
JsonSerializer.Serialize(writer, embeddedResource.Resource, McpJsonUtilities.JsonContext.Default.ResourceContents);
242+
if (embeddedResource.Meta is not null)
243+
{
244+
writer.WritePropertyName("_meta");
245+
JsonSerializer.Serialize(writer, embeddedResource.Meta, McpJsonUtilities.JsonContext.Default.JsonObject);
246+
}
216247
break;
217248

218249
case ResourceLinkBlock resourceLink:
@@ -255,6 +286,15 @@ public sealed class TextContentBlock : ContentBlock
255286
/// </summary>
256287
[JsonPropertyName("text")]
257288
public required string Text { get; set; }
289+
290+
/// <summary>
291+
/// Gets or sets metadata reserved by MCP for protocol-level metadata.
292+
/// </summary>
293+
/// <remarks>
294+
/// Implementations must not make assumptions about its contents.
295+
/// </remarks>
296+
[JsonPropertyName("_meta")]
297+
public JsonObject? Meta { get; set; }
258298
}
259299

260300
/// <summary>Represents an image provided to or from an LLM.</summary>
@@ -279,6 +319,15 @@ public sealed class ImageContentBlock : ContentBlock
279319
/// </remarks>
280320
[JsonPropertyName("mimeType")]
281321
public required string MimeType { get; set; }
322+
323+
/// <summary>
324+
/// Gets or sets metadata reserved by MCP for protocol-level metadata.
325+
/// </summary>
326+
/// <remarks>
327+
/// Implementations must not make assumptions about its contents.
328+
/// </remarks>
329+
[JsonPropertyName("_meta")]
330+
public JsonObject? Meta { get; set; }
282331
}
283332

284333
/// <summary>Represents audio provided to or from an LLM.</summary>
@@ -303,6 +352,15 @@ public sealed class AudioContentBlock : ContentBlock
303352
/// </remarks>
304353
[JsonPropertyName("mimeType")]
305354
public required string MimeType { get; set; }
355+
356+
/// <summary>
357+
/// Gets or sets metadata reserved by MCP for protocol-level metadata.
358+
/// </summary>
359+
/// <remarks>
360+
/// Implementations must not make assumptions about its contents.
361+
/// </remarks>
362+
[JsonPropertyName("_meta")]
363+
public JsonObject? Meta { get; set; }
306364
}
307365

308366
/// <summary>Represents the contents of a resource, embedded into a prompt or tool call result.</summary>
@@ -326,6 +384,15 @@ public sealed class EmbeddedResourceBlock : ContentBlock
326384
/// </remarks>
327385
[JsonPropertyName("resource")]
328386
public required ResourceContents Resource { get; set; }
387+
388+
/// <summary>
389+
/// Gets or sets metadata reserved by MCP for protocol-level metadata.
390+
/// </summary>
391+
/// <remarks>
392+
/// Implementations must not make assumptions about its contents.
393+
/// </remarks>
394+
[JsonPropertyName("_meta")]
395+
public JsonObject? Meta { get; set; }
329396
}
330397

331398
/// <summary>Represents a resource that the server is capable of reading, included in a prompt or tool call result.</summary>

src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace ModelContextProtocol.Protocol;
88
/// <remarks>
99
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
1010
/// </remarks>
11-
public class CreateMessageResult
11+
public class CreateMessageResult : Result
1212
{
1313
/// <summary>
1414
/// Gets or sets the content of the message.

src/ModelContextProtocol.Core/Protocol/ElicitResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ModelContextProtocol.Protocol;
66
/// <summary>
77
/// Represents the client's response to an elicitation request.
88
/// </summary>
9-
public class ElicitResult
9+
public class ElicitResult : Result
1010
{
1111
/// <summary>
1212
/// Gets or sets the user action in response to the elicitation.

src/ModelContextProtocol.Core/Protocol/EmptyResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ModelContextProtocol.Protocol;
66
/// Represents an empty result object for operations that need to indicate successful completion
77
/// but don't need to return any specific data.
88
/// </summary>
9-
public class EmptyResult
9+
public class EmptyResult : Result
1010
{
1111
[JsonIgnore]
1212
internal static EmptyResult Instance { get; } = new();

src/ModelContextProtocol.Core/Protocol/GetPromptResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace ModelContextProtocol.Protocol;
1515
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
1616
/// </para>
1717
/// </remarks>
18-
public class GetPromptResult
18+
public class GetPromptResult : Result
1919
{
2020
/// <summary>
2121
/// Gets or sets an optional description for the prompt.

src/ModelContextProtocol.Core/Protocol/InitializeResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace ModelContextProtocol.Protocol;
1919
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
2020
/// </para>
2121
/// </remarks>
22-
public class InitializeResult
22+
public class InitializeResult : Result
2323
{
2424
/// <summary>
2525
/// Gets or sets the version of the Model Context Protocol that the server will use for this session.

0 commit comments

Comments
 (0)