-
Notifications
You must be signed in to change notification settings - Fork 558
Add configurable JsonSerializerOptions and SchemaCreateOptions to McpServerOptions #925
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 4 commits
958d1fd
2f84c3e
bb8d2a5
f7b9dee
eca0585
542fa91
dfcd1ec
e62aae8
d56b8e5
7507081
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,87 @@ | ||
| # JSON Serialization Configuration for MCP Server | ||
|
|
||
| This document demonstrates how to configure JSON serialization options for your MCP server to handle special cases like `double.Infinity` or `NaN` values. | ||
|
|
||
| ## Problem | ||
|
|
||
| By default, JSON serialization in .NET doesn't support special floating-point values like positive/negative infinity and NaN. When a tool returns such values, you would get an error: | ||
|
|
||
| ``` | ||
| System.ArgumentException: .NET number values such as positive and negative infinity cannot be written as valid JSON. | ||
| To make it work when using 'JsonSerializer', consider specifying 'JsonNumberHandling.AllowNamedFloatingPointLiterals' | ||
| ``` | ||
|
|
||
| ## Solution | ||
|
|
||
| Configure server-wide JSON serialization options when setting up your MCP server: | ||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using ModelContextProtocol.Server; | ||
| using System.Text.Json; | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| var builder = WebApplication.CreateBuilder(args); | ||
|
|
||
| // Configure server-wide JSON serialization options | ||
| builder.Services.AddMcpServer(options => | ||
| { | ||
| options.JsonSerializerOptions = new JsonSerializerOptions(McpJsonUtilities.DefaultOptions) | ||
| { | ||
| NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | ||
| }; | ||
| }) | ||
| .WithTools<MyTools>(); | ||
|
|
||
| var app = builder.Build(); | ||
| app.Run(); | ||
|
|
||
| [McpServerToolType] | ||
| public class MyTools | ||
| { | ||
| [McpServerTool] | ||
| public static double[] GetSpecialNumbers() | ||
| { | ||
| // These values will now serialize correctly as "Infinity", "-Infinity", and "NaN" | ||
| return new[] { double.PositiveInfinity, double.NegativeInfinity, double.NaN }; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## How It Works | ||
|
|
||
| 1. The `JsonSerializerOptions` property on `McpServerOptions` provides server-wide default serialization settings | ||
| 2. All tools, prompts, and resources registered via `WithTools*`, `WithPrompts*`, and `WithResources*` will use these options by default | ||
| 3. Individual registrations can still override with their own specific options if needed | ||
|
|
||
| ## Override for Specific Tools | ||
|
|
||
| If you need different serialization options for specific tools, you can still provide them explicitly: | ||
|
|
||
| ```csharp | ||
| var customOptions = new JsonSerializerOptions | ||
| { | ||
| PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower | ||
| }; | ||
|
|
||
| builder.Services.AddMcpServer(options => | ||
| { | ||
| options.JsonSerializerOptions = McpJsonUtilities.DefaultOptions; // Default for most tools | ||
| }) | ||
| .WithTools<MyTools>() // Uses server-wide options | ||
| .WithTools<SpecialTools>(customOptions); // Uses custom options | ||
| ``` | ||
|
|
||
| ## Additional Configuration Options | ||
|
|
||
| You can configure other JSON serialization settings as needed: | ||
|
|
||
| ```csharp | ||
| options.JsonSerializerOptions = new JsonSerializerOptions(McpJsonUtilities.DefaultOptions) | ||
| { | ||
| NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, | ||
| PropertyNameCaseInsensitive = true, | ||
| AllowTrailingCommas = true, | ||
| WriteIndented = true // For debugging | ||
| }; | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| using ModelContextProtocol.Protocol; | ||
| using System.Text.Json; | ||
|
|
||
| namespace ModelContextProtocol.Server; | ||
|
|
||
|
|
@@ -60,6 +61,26 @@ public sealed class McpServerOptions | |
| /// </remarks> | ||
| public string? ServerInstructions { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the default JSON serializer options to use for tools, prompts, and resources. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <para> | ||
| /// This property provides server-wide default serialization settings that will be used | ||
| /// by all tools, prompts, and resources unless they explicitly specify their own | ||
| /// <see cref="JsonSerializerOptions"/> during registration. | ||
| /// </para> | ||
| /// <para> | ||
| /// If not set, defaults to <see cref="McpJsonUtilities.DefaultOptions"/>. | ||
| /// </para> | ||
| /// <para> | ||
| /// This is useful for configuring settings like <c>JsonNumberHandling.AllowNamedFloatingPointLiterals</c> | ||
| /// to handle special floating-point values like <see cref="double.PositiveInfinity"/>, <see cref="double.NegativeInfinity"/>, | ||
| /// and <see cref="double.NaN"/>. | ||
| /// </para> | ||
| /// </remarks> | ||
| public JsonSerializerOptions? JsonSerializerOptions { get; set; } | ||
|
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. @copilot let's see if we could also address #795 here. Please add a second 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. Added I'm working on updating all
This is a large change affecting 12+ methods. Would you prefer I complete this in the current PR or should this be split into a follow-up PR to keep the changes more focused? 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. @copilot Please do, the new property doesn't do anything unless it can be mapped to the corresponding overloads in the tool methods. 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. Completed! Added
See commit d56b8e5. The implementation is now complete and addresses both issues #636 and #795. |
||
|
|
||
| /// <summary> | ||
| /// Gets or sets whether to create a new service provider scope for each handled request. | ||
| /// </summary> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.