// Copyright (c) Microsoft. All rights reserved. using Microsoft.SemanticKernel; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; namespace MCPServer.Resources; /// /// Represents a resource definition. /// public sealed class ResourceDefinition { /// /// The kernel function to invoke the resource handler. /// private KernelFunction? _kernelFunction = null; /// /// Gets or sets the MCP resource. /// public required Resource Resource { get; init; } /// /// Gets or sets the handler for the MCP resource. /// public required Delegate Handler { get; init; } /// /// Gets or sets the kernel instance to invoke the resource handler. /// If not provided, an instance registered in DI container will be used. /// public Kernel? Kernel { get; set; } /// /// Creates a new blob resource definition. /// /// The URI of the resource. /// The name of the resource. /// The content of the resource. /// The MIME type of the resource. /// The description of the resource. /// The kernel instance to invoke the resource handler. /// If not provided, an instance registered in DI container will be used. /// /// The created resource definition. public static ResourceDefinition CreateBlobResource(string uri, string name, byte[] content, string mimeType, string? description = null, Kernel? kernel = null) { return new() { Kernel = kernel, Resource = new() { Uri = uri, Name = name, Description = description }, Handler = async (RequestContext context, CancellationToken cancellationToken) => { return new ReadResourceResult() { Contents = [ new BlobResourceContents() { Blob = Convert.ToBase64String(content), Uri = uri, MimeType = mimeType, } ], }; } }; } /// /// Invokes the resource handler. /// /// The MCP server context. /// The cancellation token. /// The result of the invocation. public async ValueTask InvokeHandlerAsync(RequestContext context, CancellationToken cancellationToken) { this._kernelFunction ??= KernelFunctionFactory.CreateFromMethod(this.Handler); this.Kernel ??= context.Server.Services?.GetRequiredService() ?? throw new InvalidOperationException("Kernel is not available."); KernelArguments args = new() { { "context", context }, }; FunctionResult result = await this._kernelFunction.InvokeAsync(kernel: this.Kernel, arguments: args, cancellationToken: cancellationToken); return result.GetValue() ?? throw new InvalidOperationException("The handler did not return a valid result."); } }