Skip to main content
MCP form elicitation is easy to get slightly wrong: a nested object on From<T>(), two properties that camelCase to the same name, a lambda that isn’t x => x.Email. Runtime skips or throws. The analyzers in McpEssentials.Core turn those mistakes into IDE squiggles and dotnet build diagnostics. They fire on FormElicitation.From<T>() and on expression starters (Exclude, String, Email, …). String-named Create() fields are whatever you add, so they are not analyzed.

Ships in Core

dotnet add package McpEssentials.Core is enough. No extra package for everyday use.

Six IDs

MCPESS001–006. Warnings, errors, and one info. All in the Usage category.

Same chain

.Exclude(x => x.Home) on the From call that seeded Home suppresses MCPESS001 for that property.

Install

Core already packs CloudNimble.McpEssentials.Analyzers.dll under analyzers/dotnet/cs. Adding Core to a project enables the diagnostics.
Rebuild after adding Core. Roslyn loads analyzers from the package; a running IDE may need a restart before squiggles appear.

What they watch

From a type

FormElicitation.From<T>("…") and new FormElicitationBuilder<T>("…"). Public instance properties are checked against the same mapping rules as runtime.

Expression starters

Exclude, String, Email, Uri, Date, DateTime, Integer, Number, Boolean, Choice, and MultiChoice when the first argument is a lambda.

The fluent chain

Exclude calls on the same expression as From are collected so skipped properties you already excluded do not warn.
FormElicitation.Create("…").String("filter") is metadata-driven. There is no CLR property to inspect, so the analyzers stay quiet. That is the path for OData $metadata and other runtime catalogs.

Diagnostics

Warning. From<T>() skips public properties the MCP form schema cannot represent: nested objects, dictionaries, TimeSpan, byte[], string[], indexers, write-only and static members.
An empty type (no public properties) is a confirm dialog and does not warn.
Error. Two properties camelCase to the same JSON name. Runtime throws InvalidOperationException at From. The analyzer fails the build instead.
Error. Expression starters and Exclude require a simple property access on the form type, the same rule as FormElicitationProperty.From. Nested members, method calls, and fields fail.
Info. Exclude of an unmappable property is a successful no-op at runtime. The analyzer tells you so you do not think you removed a field that was never seeded.
Warning. From<T>() expects a class or struct of public properties. string, primitives, enums, and arrays are not form DTOs.
Warning. Build, ToXml, ToJson, ToDefinition, and ToInputRequest seal the form. A later starter or Exclude on that local would throw at runtime.

Severity at a glance

Suppress a diagnostic

Use this when the skip is deliberate and you do not want .Exclude on the chain.
Do not suppress MCPESS002 or MCPESS003. Those match runtime exceptions. A warning you understand (MCPESS001 on a DTO you do not own) is the usual candidate.

What maps

The analyzer uses the same rules as FormElicitation.From<T>(). If Core would seed a field, MCPESS001 stays quiet.
string, Guid, char, Uri, DateOnly, DateTime, DateTimeOffset, bool, integer types, float / double / decimal, enums, [Flags] enums, and sequences of enums (TEnum[], List<TEnum>, IEnumerable<TEnum>).
Nested objects, Dictionary<,>, object, TimeSpan, byte[], string[], int[], indexers, write-only properties, static properties.

Form elicitation

Fluent schemas, ElicitAsync, and parking a form on a task.

FormElicitation API

Create, From<T>, and Bind<T>.

Authenticated tasks

Isolation, identity factory, and the samples.

Stores

Durable providers that persist the parked form.