You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fix legacy output schemas for delegating server tools - #1928
Tools wrapped in DelegatingMcpServerTool now advertise an output schema matching their structured content to clients on the 2025-06-18 and 2025-11-25 protocols.
Unwrap the delegation chain only to identify SDK-created tools, then apply the existing legacy schema transform to the outer tool's ProtocolTool. Wrapper descriptions and schema constraints are preserved. Custom tools and 2026-07-28 clients retain their existing behavior. No public API is added.
Verification
Validated with the original .NET project/MSBuild and xUnit/VSTest entries, using the prepared local dependencies without restore or downloads. Builds retained warnings-as-errors and included the referenced analyzers, hosting/task/app libraries, and test-server prerequisites.
Built tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj with --no-restore --framework net10.0 --configuration Debug: passed with zero warnings/errors on both baseline and repaired sources.
Ran the same focused regression through dotnet test against the selected baseline (3338e88) and repaired sources. The baseline produced 10 expected schema failures and 28 passes; the repair passed all 38 cases. The actual baseline production files were used with the added tests backported temporarily; repaired source bytes were restored before the after-fix build.
Ran the broader server/protocol suites through the project test entry: 1,333 passed, zero failed/skipped.
git diff --check: passed; the contribution worktree is clean.
Focused test filter: FullyQualifiedName~DelegatingToolOutputSchemaTests|FullyQualifiedName~DelegatingMcpServerToolTests|FullyQualifiedName~Sep2106ListToolsBackCompatTests
Tests used --no-build --no-restore --framework net10.0 --configuration Debug, the existing blame/crash handling and 7-minute hang budget, TRX output, and XPlat coverage collection. Coverage includes nested wrappers, wrapper overrides, nullable object and absent schemas, custom tools, both legacy protocols, and modern-client controls.
The complete platform/framework/configuration matrix, npm-backed integrations, packaging/API validation, AOT, documentation, and combined coverage workflows remain for CI. They were not run in this offline validation. A separate independent review is still required before publication.
AI assistance was used in preparing this contribution.
The production fix looks good and addresses a real compatibility issue for delegated tools with older clients.
One issue to fix before merging: the new tests use JsonSerializer.SerializeToElement(...) with anonymous objects, but the test project intentionally disables reflection-based serialization on .NET 9. This causes 15 test failures.
Could you replace those calls in DelegatingToolOutputSchemaTests.cs at lines 94-95, 161, and 172-173 with reflection-free JSON parsing? For example:
Please keep the reflection-disabled setting unchanged. The focused tests pass on the other three target frameworks, and all 1,333 server/protocol tests pass on .NET 10.
For an SDK tool with an object output schema, a delegating wrapper that expresses the equivalent schema as allOf: [innerSchema] now advertises a required result envelope to legacy clients. Invocation still uses the inner schema in CreateStructuredResponse and returns the bare object, so the content fails the advertised schema. Align the listing and invocation wrapping decisions while preserving wrapper constraints, and add a regression test for this override on both legacy protocols.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Wrapped tools returning an explicit CallToolResult can advertise a required result envelope while passing through unwrapped structured content, causing a schema mismatch for legacy clients.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Raw CallToolResult pass-throughs can return unwrapped objects while legacy tool listings require a result wrapper, breaking schema–response compatibility.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Output-schema normalization mishandles nullable tool results and recursive nullable children, causing advertised schemas to reject responses sent to legacy clients.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1916
Summary
Tools wrapped in
DelegatingMcpServerToolnow advertise an output schema matching their structured content to clients on the 2025-06-18 and 2025-11-25 protocols.Unwrap the delegation chain only to identify SDK-created tools, then apply the existing legacy schema transform to the outer tool's
ProtocolTool. Wrapper descriptions and schema constraints are preserved. Custom tools and 2026-07-28 clients retain their existing behavior. No public API is added.Verification
Validated with the original .NET project/MSBuild and xUnit/VSTest entries, using the prepared local dependencies without restore or downloads. Builds retained warnings-as-errors and included the referenced analyzers, hosting/task/app libraries, and test-server prerequisites.
tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csprojwith--no-restore --framework net10.0 --configuration Debug: passed with zero warnings/errors on both baseline and repaired sources.dotnet testagainst the selected baseline (3338e88) and repaired sources. The baseline produced 10 expected schema failures and 28 passes; the repair passed all 38 cases. The actual baseline production files were used with the added tests backported temporarily; repaired source bytes were restored before the after-fix build.git diff --check: passed; the contribution worktree is clean.Focused test filter:
FullyQualifiedName~DelegatingToolOutputSchemaTests|FullyQualifiedName~DelegatingMcpServerToolTests|FullyQualifiedName~Sep2106ListToolsBackCompatTestsTests used
--no-build --no-restore --framework net10.0 --configuration Debug, the existing blame/crash handling and 7-minute hang budget, TRX output, and XPlat coverage collection. Coverage includes nested wrappers, wrapper overrides, nullable object and absent schemas, custom tools, both legacy protocols, and modern-client controls.The complete platform/framework/configuration matrix, npm-backed integrations, packaging/API validation, AOT, documentation, and combined coverage workflows remain for CI. They were not run in this offline validation. A separate independent review is still required before publication.
AI assistance was used in preparing this contribution.