Skip to content

[WIP] Upgrade MCP C# SDK to 1.2.0 for host extension#224

Draft
liliankasem wants to merge 3 commits intomainfrom
liliankasem/mcp-sdk-1.2.0-host-ext
Draft

[WIP] Upgrade MCP C# SDK to 1.2.0 for host extension#224
liliankasem wants to merge 3 commits intomainfrom
liliankasem/mcp-sdk-1.2.0-host-ext

Conversation

@liliankasem
Copy link
Copy Markdown
Member

@liliankasem liliankasem commented Mar 31, 2026

Upgrade ModelContextProtocol from 0.4.0-preview.3 to 1.2.0 and System.Net.ServerSentEvents from 10.0.0 to 10.0.5 in the host extension (Extensions.Mcp) project.

StreamableHttpTransport rewrite

SDK 1.2.0 made all StreamableHttpServerTransport properties init-only (SessionId, Stateless,
OnSessionInitialized). We can no longer set them post-construction, so all config moved into
the constructor and object initializer. We also keep a local _sessionId field because our
wrapper needs a mutable SessionId while the SDK's is immutable after init.

OnInitRequestReceived → OnSessionInitialized

The old callback was removed. The replacement has a different signature (non-nullable
InitializeRequestParams, added CancellationToken). Since it's also init-only, we pass it
through the constructor instead of the old setter pattern.

IsStateless vs Stateless

These are two separate properties on different layers — Stateless on the SDK transport
(init-only), IsStateless on our McpExtensionTransport wrapper (used by our session management).
Both must be set; not redundant.

ToolInvocationContext.Arguments: IReadOnlyDictionary → IDictionary

The SDK changed CallToolRequestParams.Arguments to IDictionary. Our property is assigned
directly from it, so types need to match. All consumers only read from it.

Serialization: must use base types

The critical discovery: ReadOnlyMemory properties (Data, Blob) must be
serialized/deserialized via base types (ContentBlock, ResourceContents), not concrete types (
ImageContentBlock, BlobResourceContents). The MCP SDK's custom polymorphic converter only
activates through the base type. Direct concrete type serialization uses STJ's default base64
converter, causing double base64 encoding. This was the root cause of all remaining test
failures.

Other type changes

  • StructuredContent: JsonNode? → JsonElement? (use .GetRawText() instead of .ToJsonString())
  • BlobResourceContents: use FromBytes() factory instead of setting Blob directly
  • ImageContentBlock.Data / AudioContentBlock.Data: string → ReadOnlyMemory (use
    Encoding.UTF8.GetBytes(base64String))
  • System.Net.ServerSentEvents: bumped to
    10.0.5 to fix NuGet downgrade error

Issue describing the changes in this PR

resolves #221

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Additional PR information

Upgrade ModelContextProtocol from 0.4.0-preview.3 to 1.2.0 and
System.Net.ServerSentEvents from 10.0.0 to 10.0.5 in the host
extension (Extensions.Mcp) project.

Changes:
- StreamableHttpTransport: rewrite for init-only SDK properties
- StreamableHttpRequestHandler: update session creation methods
- ToolReturnValueBinder: StructuredContent JsonNode? -> JsonElement?
- ResourceReturnValueBinder: use BlobResourceContents.FromBytes()
- ToolInvocationContext: Arguments IReadOnlyDictionary -> IDictionary
- PromptInvocationContext: Arguments IReadOnlyDictionary -> IDictionary
- Test helpers: suppress MCPEXP002, use 3-arg RequestContext ctor
- Test assertions: serialize via base types for polymorphic converters

Part 1 of #222

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@liliankasem liliankasem changed the title Upgrade MCP C# SDK to 1.2.0 for host extension [WIP] Upgrade MCP C# SDK to 1.2.0 for host extension Mar 31, 2026
@liliankasem liliankasem closed this Apr 1, 2026
@liliankasem liliankasem reopened this Apr 2, 2026
liliankasem and others added 2 commits April 7, 2026 10:59
SDK 1.2.0 made StreamableHttpServerTransport.SessionId init-only but
still readable. The previous change introduced a local _sessionId field
that shadowed Transport.SessionId, creating a divergence risk. Since
nothing mutates SessionId after construction, remove the local field,
delegate the getter to Transport.SessionId (single source of truth),
and throw on the setter to make init-only semantics explicit — matching
the pattern already used by SseStreamTransport.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… 3-arg RequestContext, fix release notes

- Restore InvalidOperationException guard in DeserializeToStructuredContent
  for JSON null input (JsonElement.ValueKind check replaces the old ??
  throw pattern that doesn't work with value types)
- Migrate all test helpers from obsolete 2-arg RequestContext constructor
  to the 3-arg overload, removing all MCP9003 pragma suppressions
- Fix release notes PR reference from #222 to #224

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update host extension to latest MCP Sdk version

1 participant