Skip to content

Add NativeAOT publish coverage for ModelContextProtocol.Extensions.Apps #1659

Description

@halter73

Follow-up from PR #1484 (MCP Apps extension).

Gap

The new ModelContextProtocol.Extensions.Apps package declares IsAotCompatible=true, but nothing exercises it under NativeAOT. tests/ModelContextProtocol.AotCompatibility.TestApp only references ModelContextProtocol.Core, ModelContextProtocol, and ModelContextProtocol.AspNetCore — not Extensions.Apps. So the AOT publish job never sees the Apps code paths.

This is the reason a new { } anonymous-type bug in the capability-advertisement path (fixed during PR #1484 review) was not caught by CI. Our convention is that every shipped src/ package gets AOT publish coverage.

Proposed work

  1. Reference the package and root it in tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj:

    <ProjectReference Include="..\..\src\ModelContextProtocol.Extensions.Apps\ModelContextProtocol.Extensions.Apps.csproj" />
    <TrimmerRootAssembly Include="ModelContextProtocol.Extensions.Apps" />
  2. Extend the test app's Program.cs to actually exercise the surface, otherwise the trimmer drops the package as unused and the publish passes vacuously. At minimum: register a tool decorated with [McpAppUi], call WithMcpApps(), round-trip ListToolsAsync(), and assert the _meta.ui metadata is present.

Caveat (for expectation-setting)

This coverage would not have surfaced the specific new { } issue as an AOT analyzer warning at publish time — that value flows through IDictionary<string, object> (boxed/polymorphic), which the trimmer can't statically trace; it would only manifest as a runtime serialization fallback (or NotSupportedException in strict AOT). But the coverage still catches a broad class of other AOT problems and matches the convention for new packages.

The broader point — that the IDictionary<string, object> extension surface (MCPEXP001) is an AOT footgun in general, since anything assigned to it bypasses source-gen unless callers use JsonObject or a source-gen-registered type — may warrant its own tracking issue.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions