Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support for Resource Templates #18

Merged

Conversation

Redth
Copy link
Contributor

@Redth Redth commented Mar 21, 2025

This adds some new types and handlers to implement Resource Template functionality according to the spec.

Motivation and Context

Adds more functionality from the spec :)

How Has This Been Tested?

  • Unit tests
  • Manual testing with mcp-inspector and the Test Server project (List Templates, Read dynamic template resource, and subscribe/unsubscribe validated)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Fixes #20

@Redth Redth marked this pull request as ready for review March 21, 2025 15:57
The server was throwing if this handler wasn't specified, and it should probably be optional anyway.
Copy link
Collaborator

@PederHP PederHP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks correct to me, apart from Annotations which are a draft spec feature and not in the protocol version currently supported and advertised during initialization.

Co-authored-by: Stephen Toub <[email protected]>
Redth and others added 3 commits March 21, 2025 12:09
Co-authored-by: Stephen Toub <[email protected]>
Co-authored-by: Stephen Toub <[email protected]>
If no ListResourceTemplatesHandler is specified, use a default one that returns an empty result.
@stephentoub
Copy link
Contributor

Looks good, @Redth, thanks.

Presumably we also want the client-side equivalent, e.g.

/// <summary>
/// Retrieves a sequence of available resources from the server.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>An asynchronous sequence of resource information.</returns>
public static async IAsyncEnumerable<Resource> ListResourcesAsync(
this IMcpClient client, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
string? cursor = null;
do
{
var resources = await ListResourcesAsync(client, cursor, cancellationToken).ConfigureAwait(false);
foreach (var resource in resources.Resources)
{
yield return resource;
}
cursor = resources.NextCursor;
}
while (cursor is not null);
}
/// <summary>
/// Retrieves a list of available resources from the server.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="cursor">A cursor to paginate the results.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
public static Task<ListResourcesResult> ListResourcesAsync(this IMcpClient client, string? cursor, CancellationToken cancellationToken = default)
{
Throw.IfNull(client);
return client.SendRequestAsync<ListResourcesResult>(
CreateRequest("resources/list", CreateCursorDictionary(cursor)),
cancellationToken);
}

?

@Redth
Copy link
Contributor Author

Redth commented Mar 21, 2025

Looks good, @Redth, thanks.

Presumably we also want the client-side equivalent, e.g.

/// <summary>
/// Retrieves a sequence of available resources from the server.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>An asynchronous sequence of resource information.</returns>
public static async IAsyncEnumerable<Resource> ListResourcesAsync(
this IMcpClient client, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
string? cursor = null;
do
{
var resources = await ListResourcesAsync(client, cursor, cancellationToken).ConfigureAwait(false);
foreach (var resource in resources.Resources)
{
yield return resource;
}
cursor = resources.NextCursor;
}
while (cursor is not null);
}
/// <summary>
/// Retrieves a list of available resources from the server.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="cursor">A cursor to paginate the results.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
public static Task<ListResourcesResult> ListResourcesAsync(this IMcpClient client, string? cursor, CancellationToken cancellationToken = default)
{
Throw.IfNull(client);
return client.SendRequestAsync<ListResourcesResult>(
CreateRequest("resources/list", CreateCursorDictionary(cursor)),
cancellationToken);
}

?

Ok, added client extensions and an integration test.

Redth and others added 8 commits March 21, 2025 13:11
Co-authored-by: Stephen Halter <[email protected]>
@stephentoub stephentoub merged commit fe6b401 into modelcontextprotocol:main Mar 21, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Resource Template Support
4 participants