Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public sealed class DynamicClientRegistrationResponse
/// Gets or initializes the redirect URIs for the client.
/// </summary>
[JsonPropertyName("redirect_uris")]
public string[]? RedirectUris { get; init; }
public IList<string>? RedirectUris { get; init; }

/// <summary>
/// Gets or initializes the token endpoint authentication method.
Expand All @@ -35,13 +35,13 @@ public sealed class DynamicClientRegistrationResponse
/// Gets or initializes the grant types that the client will use.
/// </summary>
[JsonPropertyName("grant_types")]
public string[]? GrantTypes { get; init; }
public IList<string>? GrantTypes { get; init; }

/// <summary>
/// Gets or initializes the response types that the client will use.
/// </summary>
[JsonPropertyName("response_types")]
public string[]? ResponseTypes { get; init; }
public IList<string>? ResponseTypes { get; init; }

/// <summary>
/// Gets or initializes the timestamp at which the client ID was issued.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public sealed class ProtectedResourceMetadata
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("authorization_servers")]
public List<string> AuthorizationServers { get; set; } = [];
public IList<string> AuthorizationServers { get; set; } = [];

/// <summary>
/// Gets or sets the supported bearer token methods.
Expand All @@ -48,7 +48,7 @@ public sealed class ProtectedResourceMetadata
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("bearer_methods_supported")]
public List<string> BearerMethodsSupported { get; set; } = ["header"];
public IList<string> BearerMethodsSupported { get; set; } = ["header"];

/// <summary>
/// Gets or sets the supported scopes.
Expand All @@ -61,7 +61,7 @@ public sealed class ProtectedResourceMetadata
/// RECOMMENDED.
/// </remarks>
[JsonPropertyName("scopes_supported")]
public List<string> ScopesSupported { get; set; } = [];
public IList<string> ScopesSupported { get; set; } = [];

/// <summary>
/// Gets or sets the URL of the protected resource's JSON Web Key (JWK) Set document.
Expand All @@ -85,7 +85,7 @@ public sealed class ProtectedResourceMetadata
/// OPTIONAL. No default algorithms are implied if this entry is omitted. The value "none" MUST NOT be used.
/// </remarks>
[JsonPropertyName("resource_signing_alg_values_supported")]
public List<string>? ResourceSigningAlgValuesSupported { get; set; }
public IList<string>? ResourceSigningAlgValuesSupported { get; set; }

/// <summary>
/// Gets or sets the human-readable name of the protected resource intended for display to the end user.
Expand Down Expand Up @@ -157,7 +157,7 @@ public sealed class ProtectedResourceMetadata
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("authorization_details_types_supported")]
public List<string>? AuthorizationDetailsTypesSupported { get; set; }
public IList<string>? AuthorizationDetailsTypesSupported { get; set; }

/// <summary>
/// Gets or sets the list of the JWS algorithm values supported by the resource server for validating DPoP proof JWTs.
Expand All @@ -170,7 +170,7 @@ public sealed class ProtectedResourceMetadata
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("dpop_signing_alg_values_supported")]
public List<string>? DpopSigningAlgValuesSupported { get; set; }
public IList<string>? DpopSigningAlgValuesSupported { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the protected resource always requires the use of DPoP-bound access tokens.
Expand Down
2 changes: 1 addition & 1 deletion src/ModelContextProtocol.Core/Protocol/ContentBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ public sealed class ToolResultContentBlock : ContentBlock
/// audio, resource links, and embedded resources.
/// </remarks>
[JsonPropertyName("content")]
public required List<ContentBlock> Content { get; set; }
public required IList<ContentBlock> Content { get; set; }

/// <summary>
/// Gets or sets an optional structured result object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ public sealed class ListTasksResult : PaginatedResult
/// Gets or sets the list of tasks.
/// </summary>
[JsonPropertyName("tasks")]
public required McpTask[] Tasks { get; set; }
public required IList<McpTask> Tasks { get; set; }
}
2 changes: 1 addition & 1 deletion src/ModelContextProtocol.Core/Server/McpServer.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ public async ValueTask<IList<McpTask>> ListTasksAsync(
var taskResults = await ListTasksAsync(requestParams, cancellationToken).ConfigureAwait(false);
if (tasks is null)
{
tasks = new List<McpTask>(taskResults.Tasks.Length);
tasks = new List<McpTask>(taskResults.Tasks.Count);
}

foreach (var mcpTask in taskResults.Tasks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static void ListTasksResult_SerializationRoundTrip()
// Assert
Assert.NotNull(deserialized);
Assert.NotNull(deserialized.Tasks);
Assert.Equal(2, deserialized.Tasks.Length);
Assert.Equal(2, deserialized.Tasks.Count);
Assert.Equal(original.Tasks[0].TaskId, deserialized.Tasks[0].TaskId);
Assert.Equal(original.Tasks[1].TaskId, deserialized.Tasks[1].TaskId);
Assert.Equal(original.NextCursor, deserialized.NextCursor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ public async Task ListTasksAsync_ReturnsAllTasks()
var result = await store.ListTasksAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Equal(2, result.Tasks.Length);
Assert.Equal(2, result.Tasks.Count);
Assert.Contains(result.Tasks, t => t.TaskId == task1.TaskId);
Assert.Contains(result.Tasks, t => t.TaskId == task2.TaskId);
Assert.Null(result.NextCursor);
Expand Down Expand Up @@ -397,9 +397,9 @@ public async Task ListTasksAsync_SupportsPagination()
var secondPageResult = await store.ListTasksAsync(cursor: firstPageResult.NextCursor, cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Equal(100, firstPageResult.Tasks.Length);
Assert.Equal(100, firstPageResult.Tasks.Count);
Assert.NotNull(firstPageResult.NextCursor);
Assert.Equal(50, secondPageResult.Tasks.Length);
Assert.Equal(50, secondPageResult.Tasks.Count);
Assert.Null(secondPageResult.NextCursor);
}

Expand Down Expand Up @@ -779,11 +779,11 @@ public async Task ListTasksAsync_PaginationWithCustomPageSize()
var result3 = await store.ListTasksAsync(cursor: result2.NextCursor, cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Equal(10, result1.Tasks.Length);
Assert.Equal(10, result1.Tasks.Count);
Assert.NotNull(result1.NextCursor);
Assert.Equal(10, result2.Tasks.Length);
Assert.Equal(10, result2.Tasks.Count);
Assert.NotNull(result2.NextCursor);
Assert.Equal(5, result3.Tasks.Length);
Assert.Equal(5, result3.Tasks.Count);
Assert.Null(result3.NextCursor);

// Verify no duplicates across pages
Expand Down Expand Up @@ -854,7 +854,7 @@ public async Task ListTasksAsync_ConsistentWithExpiredTasksRemovedBetweenPages()
var result2 = await store.ListTasksAsync(cursor: result1.NextCursor, cancellationToken: TestContext.Current.CancellationToken);

// Assert - First page should have 5 tasks, second page should have 0 (all expired)
Assert.Equal(5, result1.Tasks.Length);
Assert.Equal(5, result1.Tasks.Count);
Assert.NotNull(result1.NextCursor);
Assert.Empty(result2.Tasks);
Assert.Null(result2.NextCursor);
Expand All @@ -874,7 +874,7 @@ public async Task ListTasksAsync_KeysetPaginationMaintainsConsistencyWithNewTask

// Get first page
var result1 = await store.ListTasksAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Equal(5, result1.Tasks.Length);
Assert.Equal(5, result1.Tasks.Count);

// Add more tasks between pages (these should appear in later queries, not retroactively in page 2)
for (int i = 10; i < 15; i++)
Expand All @@ -886,7 +886,7 @@ public async Task ListTasksAsync_KeysetPaginationMaintainsConsistencyWithNewTask
var result2 = await store.ListTasksAsync(cursor: result1.NextCursor, cancellationToken: TestContext.Current.CancellationToken);

// Assert - Second page should have 5 tasks from original set
Assert.Equal(5, result2.Tasks.Length);
Assert.Equal(5, result2.Tasks.Count);
Assert.NotNull(result2.NextCursor);

// Verify no overlap between pages
Expand Down Expand Up @@ -1128,14 +1128,14 @@ public async Task ListTasksAsync_KeysetPaginationWorksWithIdenticalTimestamps()
var result1 = await store.ListTasksAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert - First page should have 5 tasks
Assert.Equal(5, result1.Tasks.Length);
Assert.Equal(5, result1.Tasks.Count);
Assert.NotNull(result1.NextCursor);

// Get second page using cursor
var result2 = await store.ListTasksAsync(cursor: result1.NextCursor, cancellationToken: TestContext.Current.CancellationToken);

// Assert - Second page should have 5 tasks
Assert.Equal(5, result2.Tasks.Length);
Assert.Equal(5, result2.Tasks.Count);
Assert.Null(result2.NextCursor); // No more pages

// Verify no overlap between pages
Expand Down Expand Up @@ -1180,7 +1180,7 @@ public async Task ListTasksAsync_TasksCreatedAfterFirstPageWithSameTimestampAppe

// Get first page - should have 5 tasks with a cursor
var result1 = await store.ListTasksAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Equal(5, result1.Tasks.Length);
Assert.Equal(5, result1.Tasks.Count);
Assert.NotNull(result1.NextCursor);

// Now create 5 more tasks AFTER we got the first page cursor
Expand Down
Loading