Files
mcp-sdk-dotnet/Models/McpManifest.cs
logikonline 42a3e1e255 feat(mcp): add Icon, Options, and OptionsFrom to manifest models
Add Icon property to McpManifestServer. Add Options and OptionsFrom properties to McpManifestConfig for static and dynamic value lists. Add McpManifestOptionsFrom class with File and Path properties for JSONPath-based option resolution
2026-04-04 18:57:03 -04:00

191 lines
5.3 KiB
C#

using System.Text.Json;
using System.Text.Json.Serialization;
namespace McpManifest.Models;
/// <summary>
/// Root document for an mcp-manifest.json file.
/// </summary>
public sealed class McpManifestDocument
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true,
};
[JsonPropertyName("$schema")]
public string? Schema { get; set; }
[JsonPropertyName("version")]
public string Version { get; set; } = string.Empty;
[JsonPropertyName("server")]
public McpManifestServer Server { get; set; } = new();
[JsonPropertyName("install")]
public List<McpManifestInstall> Install { get; set; } = [];
[JsonPropertyName("transport")]
public string Transport { get; set; } = string.Empty;
[JsonPropertyName("endpoint")]
public string? Endpoint { get; set; }
[JsonPropertyName("config")]
public List<McpManifestConfig>? Config { get; set; }
[JsonPropertyName("scopes")]
public List<string>? Scopes { get; set; }
[JsonPropertyName("settings_template")]
public McpManifestSettingsTemplate? SettingsTemplate { get; set; }
/// <summary>
/// Parse a JSON string into an <see cref="McpManifestDocument"/>.
/// </summary>
public static McpManifestDocument Parse(string json)
{
return JsonSerializer.Deserialize<McpManifestDocument>(json, JsonOptions)
?? throw new JsonException("Deserialized manifest was null.");
}
/// <summary>
/// Load and parse an mcp-manifest.json file from disk.
/// </summary>
public static async Task<McpManifestDocument> LoadAsync(string filePath, CancellationToken cancellationToken = default)
{
var json = await File.ReadAllTextAsync(filePath, cancellationToken).ConfigureAwait(false);
return Parse(json);
}
/// <summary>
/// Serialize this document back to JSON.
/// </summary>
public string ToJson()
{
return JsonSerializer.Serialize(this, JsonOptions);
}
}
/// <summary>
/// Server metadata block.
/// </summary>
public sealed class McpManifestServer
{
[JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
[JsonPropertyName("displayName")]
public string DisplayName { get; set; } = string.Empty;
[JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;
[JsonPropertyName("version")]
public string Version { get; set; } = string.Empty;
[JsonPropertyName("author")]
public string? Author { get; set; }
[JsonPropertyName("homepage")]
public string? Homepage { get; set; }
[JsonPropertyName("repository")]
public string? Repository { get; set; }
[JsonPropertyName("license")]
public string? License { get; set; }
[JsonPropertyName("icon")]
public string? Icon { get; set; }
[JsonPropertyName("keywords")]
public List<string>? Keywords { get; set; }
}
/// <summary>
/// An installation method for the MCP server.
/// </summary>
public sealed class McpManifestInstall
{
[JsonPropertyName("method")]
public string Method { get; set; } = string.Empty;
[JsonPropertyName("package")]
public string Package { get; set; } = string.Empty;
[JsonPropertyName("source")]
public string? Source { get; set; }
[JsonPropertyName("command")]
public string Command { get; set; } = string.Empty;
[JsonPropertyName("priority")]
public int? Priority { get; set; }
}
/// <summary>
/// A configuration parameter the MCP server accepts.
/// </summary>
public sealed class McpManifestConfig
{
[JsonPropertyName("key")]
public string Key { get; set; } = string.Empty;
[JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;
[JsonPropertyName("type")]
public string Type { get; set; } = string.Empty;
[JsonPropertyName("required")]
public bool? Required { get; set; }
[JsonPropertyName("default")]
public JsonElement? Default { get; set; }
[JsonPropertyName("env_var")]
public string? EnvVar { get; set; }
[JsonPropertyName("arg")]
public string? Arg { get; set; }
[JsonPropertyName("prompt")]
public string? Prompt { get; set; }
[JsonPropertyName("options")]
public List<string>? Options { get; set; }
[JsonPropertyName("options_from")]
public McpManifestOptionsFrom? OptionsFrom { get; set; }
}
/// <summary>
/// Dynamically resolve available config values from a local file.
/// </summary>
public class McpManifestOptionsFrom
{
/// <summary>Path to a local JSON file. ~ is expanded to the user's home directory.</summary>
[JsonPropertyName("file")]
public string File { get; set; } = "";
/// <summary>JSONPath expression to extract values from the file.</summary>
[JsonPropertyName("path")]
public string Path { get; set; } = "";
}
/// <summary>
/// Pre-built template for client MCP server configuration.
/// Variables use ${key} syntax referencing config keys.
/// </summary>
public sealed class McpManifestSettingsTemplate
{
[JsonPropertyName("command")]
public string? Command { get; set; }
[JsonPropertyName("args")]
public List<string>? Args { get; set; }
}