Add McpServerPrompt / McpClientPrompt and friends (#126)

This commit is contained in:
Stephen Toub 2025-03-31 09:54:40 -04:00 • committed by GitHub
commit 5d3fb65b11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 1950 additions and 550 deletions

View file

@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Configuration;
using ModelContextProtocol.Logging;
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Protocol.Transport;

View file

@ -115,13 +115,12 @@ public static class McpClientExtensions
/// <param name="client">The client.</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>A list of all available prompts.</returns>
public static async Task<IList<Prompt>> ListPromptsAsync(
public static async Task<IList<McpClientPrompt>> ListPromptsAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
{
Throw.IfNull(client);
List<Prompt>? prompts = null;
List<McpClientPrompt>? prompts = null;
string? cursor = null;
do
{
@ -129,13 +128,10 @@ public static class McpClientExtensions
CreateRequest(RequestMethods.PromptsList, CreateCursorDictionary(cursor)),
cancellationToken).ConfigureAwait(false);
if (prompts is null)
prompts ??= new List<McpClientPrompt>(promptResults.Prompts.Count);
foreach (var prompt in promptResults.Prompts)
{
prompts = promptResults.Prompts;
}
else
{
prompts.AddRange(promptResults.Prompts);
prompts.Add(new McpClientPrompt(client, prompt));
}
cursor = promptResults.NextCursor;
@ -186,7 +182,7 @@ public static class McpClientExtensions
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>A task containing the prompt's content and messages.</returns>
public static Task<GetPromptResult> GetPromptAsync(
this IMcpClient client, string name, Dictionary<string, object?>? arguments = null, CancellationToken cancellationToken = default)
this IMcpClient client, string name, IReadOnlyDictionary<string, object?>? arguments = null, CancellationToken cancellationToken = default)
{
Throw.IfNull(client);
Throw.IfNullOrWhiteSpace(name);
@ -345,7 +341,7 @@ public static class McpClientExtensions
Throw.IfNullOrWhiteSpace(uri);
return client.SendRequestAsync<ReadResourceResult>(
CreateRequest(RequestMethods.ResourcesRead, new() { ["uri"] = uri }),
CreateRequest(RequestMethods.ResourcesRead, new Dictionary<string, object?>() { ["uri"] = uri }),
cancellationToken);
}
@ -369,7 +365,7 @@ public static class McpClientExtensions
}
return client.SendRequestAsync<CompleteResult>(
CreateRequest(RequestMethods.CompletionComplete, new()
CreateRequest(RequestMethods.CompletionComplete, new Dictionary<string, object?>()
{
["ref"] = reference,
["argument"] = new Argument { Name = argumentName, Value = argumentValue }
@ -389,7 +385,7 @@ public static class McpClientExtensions
Throw.IfNullOrWhiteSpace(uri);
return client.SendRequestAsync<EmptyResult>(
CreateRequest(RequestMethods.ResourcesSubscribe, new() { ["uri"] = uri }),
CreateRequest(RequestMethods.ResourcesSubscribe, new Dictionary<string, object?>() { ["uri"] = uri }),
cancellationToken);
}
@ -405,7 +401,7 @@ public static class McpClientExtensions
Throw.IfNullOrWhiteSpace(uri);
return client.SendRequestAsync<EmptyResult>(
CreateRequest(RequestMethods.ResourcesUnsubscribe, new() { ["uri"] = uri }),
CreateRequest(RequestMethods.ResourcesUnsubscribe, new Dictionary<string, object?>() { ["uri"] = uri }),
cancellationToken);
}
@ -560,11 +556,11 @@ public static class McpClientExtensions
Throw.IfNull(client);
return client.SendRequestAsync<EmptyResult>(
CreateRequest(RequestMethods.LoggingSetLevel, new() { ["level"] = level }),
CreateRequest(RequestMethods.LoggingSetLevel, new Dictionary<string, object?>() { ["level"] = level }),
cancellationToken);
}
private static JsonRpcRequest CreateRequest(string method, Dictionary<string, object?>? parameters) =>
private static JsonRpcRequest CreateRequest(string method, IReadOnlyDictionary<string, object?>? parameters) =>
new()
{
Method = method,

View file

@ -1,6 +1,5 @@
using System.Globalization;
using System.Runtime.InteropServices;
using ModelContextProtocol.Configuration;
using ModelContextProtocol.Logging;
using ModelContextProtocol.Protocol.Transport;
using ModelContextProtocol.Utils;

View file

@ -0,0 +1,41 @@
using ModelContextProtocol.Protocol.Types;
namespace ModelContextProtocol.Client;
/// <summary>Provides an invocable prompt.</summary>
public sealed class McpClientPrompt
{
private readonly IMcpClient _client;
internal McpClientPrompt(IMcpClient client, Prompt prompt)
{
_client = client;
ProtocolPrompt = prompt;
}
/// <summary>Gets the protocol <see cref="Prompt"/> type for this instance.</summary>
public Prompt ProtocolPrompt { get; }
/// <summary>
/// Retrieves a specific prompt with optional arguments.
/// </summary>
/// <param name="arguments">Optional arguments for the prompt</param>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>A task containing the prompt's content and messages.</returns>
public async ValueTask<GetPromptResult> GetAsync(
IEnumerable<KeyValuePair<string, object?>>? arguments = null,
CancellationToken cancellationToken = default)
{
IReadOnlyDictionary<string, object?>? argDict =
arguments as IReadOnlyDictionary<string, object?> ??
arguments?.ToDictionary();
return await _client.GetPromptAsync(ProtocolPrompt.Name, argDict, cancellationToken).ConfigureAwait(false);
}
/// <summary>Gets the name of the prompt.</summary>
public string Name => ProtocolPrompt.Name;
/// <summary>Gets a description of the prompt.</summary>
public string? Description => ProtocolPrompt.Description;
}