-
Notifications
You must be signed in to change notification settings - Fork 582
Feedback on McpClient NO MERGE #1001
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,47 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ModelContextProtocol.Protocol.Implementation name is too generic. Lots of things in this namespace named poorly. That might be OK if users don't have to deal with them, but it looks like they do. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ModelClient.CompleteAsync - naming seems off. Maybe "GetCompletion" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static ModelClient.CreateSamplingHandler - why is this factory method on ModelClient??? Maybe should be an extension method. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ModelClient - Enumerate\* vs List\* - why have these redundant methods that return the same thing just one wrapping. Can we just return IAE and have folks materialize that? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ModelClient.EnumerateToolsAsync - why accept JsonSerializerOptions on this call, it doesn't feel like something tied to enumerating tools. Would it make more sense to make this a property on the client? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SetLoggingLevel(LogLevel, CancellationToken) vs SetLoggingLevel(LoggingLevel, CancellationToken) -- WHY? Don't make these overloads, instead choose one then make conversions on the types. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LoggingLevel is the MCP type, LogLevel is the M.E.Logging type. Why shouldn't these be overloads? LoggingLevel has more values than LogLevel, so anyone with a LogLevel would be forced to call ToLoggingLevel as part of calling this. Why is that better than having it "just work"?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With an enum like this aren't folks directly calling it with a literal? Why make them choose which one to use? The reason I wrote this was because I saw both in intellisense and wondered which I should use and why they were different. Having both sets the precedent for adding more. If we choose one as the currency of this type it establishes a pattern without any promise of more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd expect it would more commonly be read from configuration or otherwise be dynamic rather than being hardcoded to a literal at the call site.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will scan for any other public surface that uses MCP primitives where we might have an ME/MEAI primitive as well. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SubscribeToResourceAsync - how are the notifications delivered? This method confused me as I don't understand what it's supposed to do. Might just need to research more. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MCP has a notifications mechanism. The client can set up a notification handler for specific notifications.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably needs better docs to connect the two methods at least. I wonder if naming could be improved to make it more obvious that the methods are complimentary. I think I understand what to pass SubscribeToResourceAsync - that's the resource "path", but no clue what I should pass for
It's unusual that this method has subscribe+unsubscribe, yet RegisterNotificationHandler just returns an IAsyncDisposable. Seems inconsistent. I also see tests that are specifying Handlers when creating the client.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We need lots more docs but it does seem this should be high on the list.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could make Subscribe return an IAsyncDisposable. That could unsubscribe. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TextContentBlock doesn't override ToString -- to get any of the data returned I need to get at protocol types, which feels wrong since those are all "raw" and not designed surface area. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jeffhandley -- here's an example of one of the "need to use Protocols" to do a basic thing. I didn't do a deep scrub of everything, but this one was a very basic scenario
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this proposing? Not exposing any of the of the protocol types in various APIs?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To use these we have to downcast. There is no DebuggerDisplay to help folks understand what they have in the IDE. We could make these more closely match the pattern used in AIContent. @ericstj to file issue - DebuggerDisplay and ToString. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Same is true for TextResourceContents. The entire content model seems pretty rough - might be better to unify on MEAI content types. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe relying only on the MEAI types is viable. They're good for passing a 90% representation around, but they will never be full-fidelity with every provider.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's fair. It would put pressure on us to add more types to MEAI if we didn't support the scenario, but it could create a common set of things that the ecosystem might build upon. We can always do that later I suppose. Perhaps we can build conversion extensions now.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We have those, e.g.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see - do we want to tell folks this is the preferred way to deal with content? I presume we still want the MCP content types to work (without using protocol types).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In what context? If you're just coding against the MCP library directly, you'd typically use the MCP types. You'd use the conversion utilities when needing to interoperate across library boundaries. For example, the McpClientTool's AIFunction.InvokeAsync override converts the MCP types to AIContent so that other components in an IChatClient pipeline can consume the content readily. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Odd that ResourceContents is plural, but ContentBlock is not. Why do we even need to different sets of types for these? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Similarly ReadResourceResult has Contents, while CallToolResult has Content, but both are ILists. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ericstj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BlobResourceContents exposes content as a normal string, which means it encoded the UTF-8 to a string, creating work for GC. Instead it should keep the UTF8 contents, and lazily decode that from base64 UTF8 to bytes (either as stream, or byte array). The same problem exists with ContentBlock types, where base-64 data is exposed as Unicode strings. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like something we control and ought to resolve before going stable.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ericstj to open an issue for properties that don't force folks to decode a string. Expose raw, and lazy byte[] |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Prompts expose arguments as types, whereas tools expose arguments as json schema. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tools in MCP expose JSON schema. Prompts do not.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, but both are describing typing of arguments on the same McpClient - it feels unusual that they have different technologies for the same/similar task.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate? What do you mean by "Prompts expose arguments as types"? There's no type information for prompts in the MCP specification, e.g. csharp-sdk/src/ModelContextProtocol.Core/Protocol/PromptArgument.cs Lines 18 to 47 in 136755f
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.