Start Debugging

MCP C# SDK 2.3: McpClient.ServerInfo ahora es anulable, y tu compilación puede notarlo

ModelContextProtocol 2.3.0, publicado el 20 de octubre de 2026, cambia McpClient.ServerInfo de Implementation a Implementation? porque los servidores 2026-07-28 pueden omitir su identidad en server/discover. Aquí está el porqué, qué se rompe con advertencias como errores y la corrección de una línea.

El MCP C# SDK 2.3.0 se publicó el 20 de octubre de 2026 y trae un cambio que normalmente no esperarías en una versión menor: McpClient.ServerInfo ahora está anotado como Implementation? en lugar de Implementation. La firma del CLR es idéntica, así que nada se rompe en tiempo de ejecución ni para los llamadores ya compilados. Lo que se rompe es cualquier proyecto con <Nullable>enable</Nullable> y <TreatWarningsAsErrors>true</TreatWarningsAsErrors> que acceda directamente a la propiedad.

Por qué un servidor conectado puede no tener identidad

En la revisión 2026-07-28 del protocolo, el handshake es server/discover en lugar del initialize heredado. Durante el descubrimiento, los metadatos io.modelcontextprotocol/serverInfo son opcionales. Un servidor puede responder al descubrimiento, anunciar sus herramientas y atender llamadas sin decir nunca quién es.

Antes de la 2.3.0, el SDK no modelaba ese caso. La conexión a un servidor así tenía éxito, pero leer ServerInfo después lanzaba InvalidOperationException, la misma excepción que obtienes cuando el cliente no está conectado en absoluto. Un servidor perfectamente válido parecía una conexión rota. El PR #1903 lo corrigió devolviendo null:

public override Implementation? ServerInfo => _serverCapabilities is null
    ? throw new InvalidOperationException("The client is not connected.")
    : _serverInfo;

De ahí salen tres reglas:

Los metadatos mal formados siguen haciendo fallar la conexión con una JsonException, así que null significa realmente “no proporcionado”, no “basura”.

La corrección en el código del cliente

Código como este ahora produce CS8602 en el acceso a .Name:

await using var client = await McpClient.CreateAsync(transport);

logger.LogInformation("Connected to {Server} {Version}",
    client.ServerInfo.Name, client.ServerInfo.Version);

Maneja el caso nulo de forma explícita:

await using var client = await McpClient.CreateAsync(transport);

var name = client.ServerInfo?.Name ?? "Unknown server";
var version = client.ServerInfo?.Version ?? "n/a";

logger.LogInformation("Connected to {Server} {Version}", name, version);

Resiste la tentación del operador !. Silencia la advertencia y trae de vuelta una NullReferenceException la primera vez que alguien apunte tu cliente a un servidor que solo hace descubrimiento. Las notas de la versión también son tajantes en que esta identidad autodeclarada “no debe usarse para decisiones de seguridad”. Si tu código controla el acceso a herramientas según ServerInfo.Name, eso ya estaba mal, y un null aquí es un buen momento para reemplazarlo por una configuración que tú controles.

El resto de la 2.3.0

La versión trae sobre todo trabajo de interoperabilidad y confiabilidad que vale la pena adoptar de todos modos:

Actualizar es solo cambiar la versión del paquete:

dotnet add package ModelContextProtocol --version 2.3.0

Si todavía estás en la 1.x, haz primero la migración de 1.x a 2.x, luego compila con las advertencias como errores y deja que el compilador te muestre cada acceso a ServerInfo.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Volver