MCP C# SDK Array Tool Outputs: Stop Looking for a `result` Wrapper A developer demonstrated that the MCP C# SDK's array tool outputs no longer require a `result` wrapper after the protocol upgrade to 2026-07-28. The SDK handles negotiation between protocol versions, emitting a compatibility envelope for older clients. The developer provided a verifier that tests both protocol versions offline to make the contract change explicit. MCP C SDK array tool outputs are easy to misread after a protocol upgrade. A client written around the older wire shape may always reach for structuredContent.result . Once both sides negotiate MCP 2026-07-28 , an array is an array and a scalar is a scalar. There is no required wrapper to unwrap. I treat that as a contract change worth testing at the transport boundary. A unit test against the C return type cannot tell me what tools/list advertised or what tools/call actually carried. The small verifier below runs both protocol versions offline and makes the difference explicit. The MCP 2026-07-28 tools specification https://modelcontextprotocol.io/specification/2026-07-28/server/tools allows structuredContent to contain any JSON value: object, array, string, number, Boolean, or null. An outputSchema may likewise describe an array or primitive at its root. The schema still matters: servers must return content that conforms to it, and clients should validate the result. This is different from the older object-only convention. Under 2025-11-25 , a tool returning string needs an object envelope such as this: { "structuredContent": { "result": "starter", "growth", "enterprise" } } The modern form is the value itself: { "structuredContent": "starter", "growth", "enterprise" } The stable MCP C SDK handles this negotiation. Its v2.0.0 release notes https://github.com/modelcontextprotocol/csharp-sdk/releases/tag/v2.0.0 call out direct non-object tool results, while the current v2.2.0 tools guide https://csharp.sdk.modelcontextprotocol.io/concepts/tools/tools.html documents UseStructuredContent . For a down-level client, the SDK still emits the compatibility envelope. I do not need a second handler or a hand-written version switch. The sample pins the current stable package and targets .NET 10: