Commit graph csharp-sdk/tests/ModelContextProtocol.Tests
Author SHA1 Message Date
Mehran Davoudi
15d1271212
Add ElicitAsync<T> (#630) (#715)
* Add ElicitAsync<T> (#630)

- Refactored `ElicitResult` to a generic class `ElicitResult<T>` for typed content.
- Added `ElicitAsync<T>` method in `McpServerExtensions.cs` to request user input and construct schemas based on type `T`.
- Implemented schema building logic to handle primitive types and enums, ignoring unsupported types.
- Introduced `ElicitationTypedTests.cs` for testing the new elicitation functionality with typed forms.
- Verified naming policies in tests to ensure correct serialization casing.
- Defined `SampleForm` and `CamelForm` classes for expected input shapes, including unsupported properties for schema testing.
- Created JSON serialization contexts for both forms using source generation for improved performance.

* Fix the enum issue. for ElicitAsync<T>.

* Use AIJsonUtilities.CreateJsonSchema to create PrimitiveSchemaDefinition. #630

Renamed `BuildRequestSchemaFor<T>` to `BuildRequestSchema<T>`.
Updated the implementation to use `CreatePrimitiveSchema` and
enhanced type checks for supported primitives with
`AIJsonUtilities.CreateJsonSchema`. Streamlined handling of
unsupported types by consolidating return statements.

* Simplify ElicitAsync for schema validation. #630

Simplified the `ElicitAsync` method in `McpServerExtensions.cs` by removing unnecessary JSON object construction and directly deserializing `raw.Content`. Updated `CreatePrimitiveSchema` to use `JsonTypeInfo` for type checking and adjusted return logic for unsupported types.

In `ElicitationTypedTests.cs`, modified the `Can_Elicit_Typed_Information` test to account for the new `Created` property in `SampleForm`, increasing the expected property count from 5 to 6. Added assertions for the type and format of the `Created` property and included its deserialization in the test setup.

* Add error handling for unsupported elicitation types #630

Introduce exception handling in `McpServerExtensions.cs` for unsupported types. Add a test case in `ElicitationTypedTests.cs` to verify exception throwing for unsupported types. Define a new `UnsupportedForm` class with nested properties and include JSON serialization attributes for proper handling.

* Validate generic types in BuildRequestSchema #630

Introduce validation to ensure only object types are supported for elicitation requests in the `BuildRequestSchema` method. An exception is thrown for non-object types. Update the test suite with a new test case to verify this behavior, ensuring that an exception is raised when eliciting a non-object generic type (e.g., string) and that the elicitation handler is not invoked in this scenario.

* Move nullable types handling logic to ElicitationRequestParams.Coverter. #630

* Add schema validation for elicitation requests

Introduce `TryValidateElicitationPrimitiveSchema` method to validate JSON schemas for elicitation requests. This method checks for object type, verifies the "type" property, and ensures compliance with allowed properties based on primitive types (string, boolean, number). Integrate this validation in the `BuildRequestSchema` method to ensure generated schemas are valid before further processing.

* Refactor nullable type pattern matching. #630

* Update src/ModelContextProtocol.Core/Server/McpServerExtensions.cs

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Update src/ModelContextProtocol.Core/Server/McpServerExtensions.cs

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Update src/ModelContextProtocol.Core/Server/McpServerExtensions.cs

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Update src/ModelContextProtocol.Core/Server/McpServerExtensions.cs

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Update src/ModelContextProtocol.Core/Server/McpServerExtensions.cs

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Add ElicitResultSchemaCache. #630

* Prepopulate elicit schema validation logic. #630

- Introduced `LazyElicitAllowedProperties` to cache allowed property names for primitive types, replacing hardcoded logic.
- Streamlined `TryValidateElicitationPrimitiveSchema` method by consolidating type checks using pattern matching.
- Removed manual addition of allowed properties and now retrieve them directly from the new dictionary.
- Updated handling of "integer" type to be treated as "number" for consistency.

* Use Nullable.GetUnderlyingType to handle nullable types on elicitation. #630

- Update `ElicitRequestParams.cs` to throw a `JsonException` for non-string "type" properties, simplifying error handling.
- Modify `CreatePrimitiveSchema` in `McpServerExtensions.cs` to better handle nullable types and improve error messages.
- Revise `TryValidateElicitationPrimitiveSchema` to accept schema as the first parameter, enhancing clarity in error reporting.
- Simplify validation logic for the "type" keyword by directly retrieving string values, ensuring unsupported "type" arrays are flagged as errors.

* Rename static field.

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Fix static field renamings. #630

* Make BuildRequestSchema non-generic. #630

* Avoid closure allocation for serializerOptions on netcore  #630

Updated the `GetOrAdd` method to use a generic type parameter for .NET, allowing for better handling of `JsonSerializerOptions`. Retained the original implementation for other frameworks to ensure compatibility.

* Refactor ElicitRequestParams and McpServerExtensions. #630

- Simplified "type" property handling in Converter.
- Changed s_lazyElicitAllowedProperties to nullable type.
- Updated ElicitAsync to use static lambda for clarity.
- Refactored CreatePrimitiveSchema to handle nullable types.
- Initialized allowed properties in TryValidateElicitationPrimitiveSchema.
- Updated ElicitationTypedTests for naming conventions and added tests for nullable properties.
- Enforced required properties in SampleForm and introduced NullablePropertyForm.
- Added JSON source generation context for NullablePropertyForm.

* Remove reduntant checks. #630

Refactor JSON schema type handling and add integer support

This commit simplifies the validation logic for the `type` property in the JSON schema by removing unnecessary conditional checks. It directly retrieves the string value from `typeProperty` and assigns it to `typeKeyword`. Additionally, it enhances the `s_lazyElicitAllowedProperties` dictionary to include support for the `integer` type, allowing it to be recognized as a valid type with its corresponding allowed properties.

* Add IsAccepted property and update ElicitAsync return type

- Introduced `IsAccepted` property in `ElicitResult` and `ElicitResult<T>` to indicate if the action was accepted.
- Changed `ElicitAsync<T>` to return `ValueTask<ElicitResult<T>>` instead of `ValueTask<ElicitResult<T?>>`, ensuring non-nullable results.
- Updated return statements in `ElicitAsync<T>` to reflect the new return type, treating `Content` as non-nullable.

* Rename to s_elicitAllowedProperties

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Fix renaming s_elicitAllowedProperties. #630

* Remove unnecessary json attributes. #630

* Improve xml comment

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>

* Remove extra IsAccepted property. #630

* Use IsAccepted for checks.

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Add IsAccepted to non-generic ElicitResult.

---------

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
2025-09-15 17:50:50 +03:00
Stephen Halter
d344c65120
Add middleware and authz support for server-side handlers (#733) 2025-09-10 10:07:45 -07:00
Stephen Toub
2fa658e439
Add WithXx overloads that take target instance (#706)
* Add WithXx overloads that take target instance
* Special-case enumerables
2025-08-26 09:38:53 -07:00
Eirik Tsarpalis
f2dc714cd5
Update packages and Infra (#732)
* Update packages and Infra

* Update Directory.Packages.props

* Update Directory.Packages.props

* Install mono on macos gh-actions machines

* Skip failing test

* Attempt to fix failing macos test.
2025-08-26 17:28:35 +03:00
Stephen Toub
70960e1f1b
Remove special-casing of string enumerables in McpServerTool (#699)
We special-case string enumerables, translating them to an array of text content blocks, but other enumerables just get serialized, and there's a reasonable expectation that returning a string[] would produce a JSON array of strings. Just delete the special-casing.
2025-08-13 13:05:42 -04:00
Copilot
e1a2564a4e
Fix NotSupportedException when returning IEnumerable<ContentBlock> (#675) 2025-08-05 14:36:11 -07:00
Copilot
650df63194
Fix ResourceLinkBlock deserialization by adding missing "name" case (#645)
* Initial plan

* Initial analysis and plan for ResourceLinkBlock deserialization fix

Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>

* Fix ResourceLinkBlock deserialization by adding missing "name" case

Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>

* Remove unnecessary dotnet-install.sh file

Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>

* Use const for JSON string variables and improve indentation

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

* Remove temporary backup file

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

* Change JSON variable names to use PascalCase (Json) as requested

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
2025-07-23 19:52:45 +03:00
Eirik Tsarpalis
3156818d66
Update MEAI version and add regression test for #601. (#628) 2025-07-16 16:17:49 +03:00
Eirik Tsarpalis
aa75f6f37e
Enable netfx testing. (#588)
* Enable netfx testing.

* Skip impacted tests and re-enable netfx testing.

* Remove redundant comment.

* Remove unnecessary project configuration.

* Simplify test server copying.
2025-07-08 18:50:37 +03:00
Den Delimarsky 🌺
cdf88e7f5d
Authorization Support (Using ASP.NET Core Native AuthN/AuthZ Integration) (#377) 2025-07-03 14:39:28 -07:00
Stephen Toub
4411f1ce5e
Change default name casing of McpServerXx.Create tools/prompts/resources (#568) 2025-07-01 16:40:42 -04:00
Stephen Toub
4e290f8de9
Add CallToolResult.ToChatMessage extension method (#575)
To simplify non-AIFunction usage getting a ChatMessage with the appropriate FunctionResultContent.
2025-07-01 07:09:49 -04:00
Stephen Toub
ab51400ba0
Make CallToolResult.IsError optional (#573)
Match the spec, and avoid sending the property in the success case.
2025-06-30 11:35:07 -04:00
Stephen Toub
f3539cc2ca
Enable injecting IMcpServer and friends into ctors (#570) 2025-06-30 10:58:08 -04:00
Eirik Tsarpalis
55bda787ae
Styling: remove a few redundant parens from object initializer expressions. (#548)
* Styling: remove a few redundant parens from object initializer expressions.

* Fix build error.
2025-06-26 16:55:54 +03:00
Stephen Toub
068f0418fe
Fix deserialization of PrimitiveSchemaDefinition (#537)
This is preventing clients from correctly handling elicitation requests.
2025-06-24 08:48:12 -04:00
Eirik Tsarpalis
0b26b7bf22
Fix URI template derivation and lookup (#530)
* Use lowercase host in resource URI template derivation.

* Address feedback

* Add casing testing for non-templated resource lookups.

* Fix uri primitive lookup

* Use a hardcoded mcp hostname in derived resource template URIs and ensure built-in resources work with the VS Code client.

* Address feedback

* Fix equality comparison

* Use dedicated type for resource collections.
2025-06-23 19:49:38 +03:00
Stephen Halter
befa31d5c9
Send MCP-Protocol-Version header in Streamable HTTP client transport (#500) 2025-06-17 14:27:26 -07:00
Stephen Toub
b9b4a23005
Add a callback for receiving stderr output (#525)
* Add a callback for receiving stderr output

* Add asserts to test
2025-06-17 16:03:20 -04:00
Stephen Toub
2bcff315f8
Update content according to latest spec (#513)
* Update content according to latest spec

* Add Title to a bunch of types

* Add _meta to lots of types

* Address feedback, more cleanup, fix NAOT test failure
2025-06-16 19:39:41 -04:00
Sven Boemer
28d65470f4
Update Microsoft.Extensions.AI version & expose JSON configuration on McpServerResourceCreateOptions (#511)
* Update Microsoft.Extensions.AI version

* Update Microsoft.Extensions.AI.OpenAI

* Fix failing tests; add JSON configuration options to McpServerResourceCreateOptions.

* Replace temporary code with `AIFunction.ReturnJsonSchema`

---------

Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
2025-06-13 13:50:14 +01:00
Eirik Tsarpalis
1e8fb04037
Make enums serialize as strings if using the reflection-based serializer. (#473)
* Make enums serialize as strings if using the reflection-based serializer.

* Remove unnecessary partial

* Use an explicit reflection-based converter for enums.

* Update comments

* Make the reflection-based enum converter public.
2025-06-12 18:25:54 +03:00
Eirik Tsarpalis
d7d9eab3f8
Pass session id's to MCP endpoints. (#466)
* Pass session id's to MCP endpoints.

* Update src/ModelContextProtocol/Client/McpClient.cs

Co-authored-by: Stephen Halter <halter73@gmail.com>

* Update src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs

Co-authored-by: Stephen Halter <halter73@gmail.com>

* Make init callback asynchronous.

* Address feedback.

---------

Co-authored-by: Stephen Halter <halter73@gmail.com>
2025-06-12 17:56:57 +03:00
Eirik Tsarpalis
fa017c04c3
Add structured output/output schema support for server-side tools. (#480)
* Add structured output/output schema support for server-side tools.

* Address feedback.

* Add McpServerToolAttribute.UseStructuredContent

---------

Co-authored-by: Stephen Toub <stoub@microsoft.com>
2025-06-06 00:20:12 -07:00
Stephen Halter
703b0fe50b
Add ModelContextProtocol.Core package (#428) 2025-06-02 15:16:45 -07:00
Stephen Toub
5cc7c00456
Add elicitation capability (#467)
* Add elicitation capability
2025-05-29 22:03:03 -04:00
Stephen Halter
317f468807
Automatically fall back from Streamable HTTP to SSE on the client by default (#456) 2025-05-28 11:06:58 -07:00
кɵɵѕнī
adb2098e4d
Log tool invocation errors (#447)
* Log tool errors
* add test and implement source generated logging
2025-05-23 14:48:47 -07:00
Stephen Toub
106ab8064f
Clean up namespaces (#410)
No meaningful code changes, just lots of namespace shuffling to have fewer namespaces and to put things in better namespaces.
2025-05-14 14:50:26 -04:00
Stephen Toub
c11c634945
Improve exception diagnostics for stdio client (#376)
* Improve exception diagnostics for stdio client

Track the last several lines of stderr and include those in an exception created as part of CleanupAsync if the server process has already exited. This is based on an assumption that the server should never exit prior to CleanupAsync being called.

* Address feedback and fix test failure
2025-05-14 10:46:49 -04:00
Stephen Toub
8d4f51da50
Fix McpServerResource registration (#411)
- Add missing filling of ResourceCollection in McpServerOptionsSetup
- Remove AIFunctionMcpServerXx.ToString overrides; for resources, it was changing behavior undesirably, and for the others it was duplicate code.
- Fix notification method used for resource list changes.
- Fix type in WithResources parameter name.
2025-05-14 09:08:59 -04:00
Stephen Halter
ce9f73f43f
Add stateless Streamable HTTP support (#392)
- It allows a single MCP session spanning multiple requests
  to be handled by different servers without sharing state
- It does require the servers share data protection keys, but this
  is standard for ASP.NET Core cookies and antiforgery as well
- It immediately throws for unsupported operations like sampling
2025-05-14 04:51:03 -07:00
Stephen Toub
ca3a8ab921
Update M.E.AI.Abstractions to 9.5.0-preview.1.25262.9 (#412) 2025-05-14 13:24:24 +03:00
Stephen Toub
61092e0266
Update to latest M.E.AI version (#401) 2025-05-10 07:53:04 -04:00
Stephen Toub
d86b3277d4
Add McpServer/ClientResource{Template} and friends (#391)
* Add McpServer/ClientResource{Template} and friends

This PR copies the same design used by tools and prompts to add McpServerResource, McpServerResourceAttribute, McpServerResourceTypeAttribute, McpClientResource, and then all of those for ResourceTemplate as well.

Unlike the others, [McpServerResource] is permitted not only on methods but also on properties. This convenience is afforded because such resources aren't parameterized, and thus can be easily modeled as properties, likely auto-props, e.g.
```C#
[McpServerResource]
public static BlobResourceContents MyAmazingData { get; } = Create();
```

Details about resources can be encoded into the attributes or provided via McpServerResource{Template}.Create methods. If not URI is explicitly defined, one is derived from the member name and arguments. For templates, this means manufacturing a URI template that includes variables for all non-DI parameters.

This also fixes a few issues discovered along the way:
- McpClientExtensions are updated to use `ValueTask<T>` instead of `Task<T>` where relevant.
- McpServerPrompt was missing handling for progress notifications; that's been rectified. It was also missing configuring the description on the ProtocolPrompt.
- Renamed IMcpServerPrimitive.Name to Id. For resources, names aren't unique.
- After going back and forth, updated McpServer to not fail for missing handlers and to instead register default handlers. It simplifies the implementation and makes it more consistent.
- Added a bunch of primitive types into the McpJsonUtilities JSON source generator context so that such primitives are usable with tools/prompts/resources without folks being required to add them into their own context for Native AOT. I think we should consider pushing this down to AIJsonUtilities, instead, and that will then flow up to McpJsonUtilities automatically.

* Address feedback
2025-05-09 18:21:11 -04:00
Stephen Toub
b743889987
Update System and M.E.AI dependencies (#374) 2025-05-01 11:25:17 -04:00
Stephen Halter
e913d80f05
Add client-side Streamable HTTP transport support (#356) 2025-04-30 17:21:43 -07:00
Adrian Cole
17a94272d9
Backfills trace injection test and migrates from request.params to request.params._meta (#360)
* Adds test to show where trace IDs are encoded

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>

* update impl to params._meta

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>

---------

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>
2025-04-29 12:38:14 -04:00
1357310795
e190844218
Add SchemaCreateOptions in McpServerToolCreateOptions/McpServerPromptCreateOptions (#354)
* Add SchemaCreateOptions in McpServerToolCreateOptions

* Use TransformSchemaNode for SchemaCreateOptions testing

* Add SchemaCreateOptions in McpServerPromptCreateOptions also
2025-04-25 16:36:00 +03:00
Stephen Halter
e3ff552824
Improve testing for StreamableHttpHandler and IdleTrackingBackgroundService (#345)
* Add idle session pruning tests
* Remove redundant CTS from StreamableHttpHandler
  * StreamableHttpServerTransport.HandlePostRequest already creates the equivelant CTS
    which DeleteRequest_CompletesSession_WhichCancelsLongRunningToolCalls verifies
* Fix accept header validation for GET
* Use InvalidOperationException for transport-not-connected errors in doc comments
* Fix flaky Cancellation_ThrowsCancellationException test
2025-04-24 10:49:02 -07:00
Stephen Halter
7dcba357d4
Add server-side Streamable HTTP transport support (#330)
- Changes IJsonRpcMessage to an abstract base class so RelatedTransport will always be available
- Streamable HTTP supports multiple concurrent HTTP request with their own indpendent SSE response streams
- RelatedTransport indicates the source or destination of the JsonRpcMessage

- Changes the default RequestId to a JSON number for better compatibility with MCP servers in the wild
2025-04-18 17:07:23 -07:00
Stephen Toub
7d77be68cf
Clean up (use of) McpException and McpTransportException (#321)
* Clean up (use of) McpException

* Replace McpTransportException with InvalidOperationException

* Add cancellation test
2025-04-18 09:25:29 -07:00
Stephen Toub
d65ddce268
Fix HandlesIProgressParameter test sporadically failing in CI (#327) 2025-04-18 09:23:19 -07:00
Stephen Toub
b0cd6541ce
Add WithTools/Prompts overloads that accept McpServerTool/Prompts (#319)
To avoid folks needing to know how you should be registering tool instances into DI.
2025-04-16 15:06:19 -04:00
Stephen Toub
227f440ab9
Support progress notifications with McpClientTool and McpClientExtensions.CallToolAsync (#312) 2025-04-16 09:03:07 -04:00
Stephen Toub
90748b1198
Delete faulty assert (#313)
We need better coverage of Subscribe/Unsubscribe separately, but for now this assert is bad.
2025-04-15 16:00:43 -07:00
Stephen Halter
9c124b1770
Add StreamableHttpHandler and WithHttpTransport (#291)
* Simplify ModelContextProtocol.AspNetCore README

* Add StreamableHttpHandler

* Use "docker info" in CheckIsDockerAvailable

* Call WithHttpTransport in samples, tests and README

* Cleanup test namespaces

* Add CanConnect_WithMcpClient_AfterCustomizingRoute test

* Simplify relative URI handling

* Handle request made directly to the MapMcp route pattern

* Add Messages_FromNewUser_AreRejected test

* Fix README

* Shorten UserIdClaim ValueTuple names

* Remove MaxReconnectAttempts and ReconnectDelay from SseClientTransportOptions

- Add proper AdditionalHeaders support
2025-04-14 10:15:33 -04:00
Liudmila Molkova
d6cc65aced
OpenTelemetry: context propagation and semconv update (#262) 2025-04-12 22:12:11 -04:00
Stephen Toub
f4c87f5e2f
Wrap each request in a service scope (#276)
* Wrap each request in a service scope

* Change request/notification delegates to return ValueTask

* Address feedback
2025-04-11 19:19:12 -04:00
Eirik Tsarpalis
ce4e6586d2
Expose a JsonSerializerOptions setting in the prompts APIs (#279)
* Expose a JsonSerializerOptions setting in the prompts APIs

* Change namespace for workaround converter.
2025-04-11 18:02:21 +01:00