/* * Copyright (C) 2025 Mcp-Vala Project * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Mcp-Vala Project */ /** * Prompt-related data types for MCP protocol. * * This namespace contains all prompt-related types defined by the MCP specification, * including prompt definitions, arguments, and related structures. */ namespace Mcp.Prompts.Types { /** * Prompt definition as defined by MCP protocol. */ public class PromptDefinition : GLib.Object { /** * Name of the prompt. */ public string name { get; set; } /** * Optional title of the prompt. */ public string? title { get; set; } /** * Optional description of the prompt. */ public string? description { get; set; } /** * List of prompt arguments. */ public Gee.ArrayList arguments { get; set; } /** * Creates a new PromptDefinition. * * @param name Name of the prompt */ public PromptDefinition (string name) { this.name = name; this.arguments = new Gee.ArrayList (); } /** * Serializes PromptDefinition to GLib.Variant. * * @return A GLib.Variant representing this PromptDefinition */ public Variant to_variant () { var builder = Mcp.Types.VariantUtils.new_dict_builder (); builder.add ("{sv}", "name", new Variant.string (name)); Mcp.Types.VariantUtils.add_string_if_not_null (builder, "title", title); Mcp.Types.VariantUtils.add_string_if_not_null (builder, "description", description); // Serialize arguments array var args_builder = Mcp.Types.VariantUtils.new_dict_array_builder (); foreach (var arg in arguments) { args_builder.add_value (arg.to_variant ()); } builder.add ("{sv}", "arguments", args_builder.end ()); return builder.end (); } /** * Creates a PromptDefinition from GLib.Variant. * * @param variant The GLib.Variant to deserialize * @return The deserialized PromptDefinition * @throws Error If deserialization fails */ public PromptDefinition.from_variant (Variant variant) throws Error { if (!variant.is_of_type (VariantType.VARDICT)) { throw new Mcp.Core.McpError.PARSE_ERROR ("PromptDefinition must be a dictionary"); } if (variant.lookup_value ("name", null) == null) { throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing name in PromptDefinition"); } this.name = variant.lookup_value ("name", VariantType.STRING).get_string (); if (variant.lookup_value ("title", null) != null) { this.title = variant.lookup_value ("title", VariantType.STRING).get_string (); } if (variant.lookup_value ("description", null) != null) { this.description = variant.lookup_value ("description", VariantType.STRING).get_string (); } this.arguments = new Gee.ArrayList (); if (variant.lookup_value ("arguments", null) != null) { var args = variant.lookup_value ("arguments", new VariantType ("aa{sv}")); for (size_t i = 0; i < args.n_children (); i++) { var arg = new PromptArgument.from_variant (args.get_child_value (i)); arguments.add (arg); } } } } /** * Prompt argument definition. */ public class PromptArgument : GLib.Object { /** * Name of the argument. */ public string name { get; set; } /** * Optional title of the argument. */ public string? title { get; set; } /** * Optional description of the argument. */ public string? description { get; set; } /** * Whether the argument is required. */ public bool required { get; set; default = false; } /** * Creates a new PromptArgument. * * @param name Name of the argument */ public PromptArgument (string name) { this.name = name; } /** * Serializes PromptArgument to GLib.Variant. * * @return A GLib.Variant representing this PromptArgument */ public Variant to_variant () { var builder = Mcp.Types.VariantUtils.new_dict_builder (); builder.add ("{sv}", "name", new Variant.string (name)); Mcp.Types.VariantUtils.add_string_if_not_null (builder, "title", title); Mcp.Types.VariantUtils.add_string_if_not_null (builder, "description", description); builder.add ("{sv}", "required", new Variant.boolean (required)); return builder.end (); } /** * Creates a PromptArgument from GLib.Variant. * * @param variant The GLib.Variant to deserialize * @return The deserialized PromptArgument * @throws Error If deserialization fails */ public PromptArgument.from_variant (Variant variant) throws Error { if (!variant.is_of_type (VariantType.VARDICT)) { throw new Mcp.Core.McpError.PARSE_ERROR ("PromptArgument must be a dictionary"); } if (variant.lookup_value ("name", null) == null) { throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing name in PromptArgument"); } this.name = variant.lookup_value ("name", VariantType.STRING).get_string (); if (variant.lookup_value ("title", null) != null) { this.title = variant.lookup_value ("title", VariantType.STRING).get_string (); } if (variant.lookup_value ("description", null) != null) { this.description = variant.lookup_value ("description", VariantType.STRING).get_string (); } if (variant.lookup_value ("required", null) != null) { this.required = variant.lookup_value ("required", VariantType.BOOLEAN).get_boolean (); } } } /** * Result of getting a prompt. */ public class GetPromptResult : GLib.Object { /** * Optional description of the prompt result. */ public string? description { get; set; } /** * List of prompt messages. */ public Gee.ArrayList messages { get; set; } /** * Creates a new GetPromptResult. */ public GetPromptResult () { messages = new Gee.ArrayList (); } /** * Serializes GetPromptResult to GLib.Variant. * * @return A GLib.Variant representing this GetPromptResult */ public Variant to_variant () { var builder = Mcp.Types.VariantUtils.new_dict_builder (); Mcp.Types.VariantUtils.add_string_if_not_null (builder, "description", description); // Serialize messages array var messages_builder = Mcp.Types.VariantUtils.new_dict_array_builder (); foreach (var message in messages) { messages_builder.add_value (message.to_variant ()); } builder.add ("{sv}", "messages", messages_builder.end ()); return builder.end (); } /** * Creates a GetPromptResult from GLib.Variant. * * @param variant The GLib.Variant to deserialize * @return The deserialized GetPromptResult * @throws Error If deserialization fails */ public GetPromptResult.from_variant (Variant variant) throws Error { if (!variant.is_of_type (VariantType.VARDICT)) { throw new Mcp.Core.McpError.PARSE_ERROR ("GetPromptResult must be a dictionary"); } if (variant.lookup_value ("description", null) != null) { this.description = variant.lookup_value ("description", VariantType.STRING).get_string (); } this.messages = new Gee.ArrayList (); if (variant.lookup_value ("messages", null) != null) { var messages = variant.lookup_value ("messages", new VariantType ("aa{sv}")); for (size_t i = 0; i < messages.n_children (); i++) { var message = new PromptMessage.from_variant (messages.get_child_value (i)); this.messages.add (message); } } } } /** * Prompt message. */ public class PromptMessage : GLib.Object { /** * Role of the message sender ("user" or "assistant"). */ public string role { get; set; } /** * Content of the message. */ public Mcp.Types.Common.ContentBlock content { get; set; } /** * Creates a new PromptMessage. * * @param role Role of the message * @param content Content of the message */ public PromptMessage (string role, Mcp.Types.Common.ContentBlock content) { this.role = role; this.content = content; } /** * Serializes PromptMessage to GLib.Variant. * * @return A GLib.Variant representing this PromptMessage */ public Variant to_variant () { var builder = Mcp.Types.VariantUtils.new_dict_builder (); builder.add ("{sv}", "role", new Variant.string (role)); builder.add ("{sv}", "content", content.to_variant ()); return builder.end (); } /** * Creates a PromptMessage from GLib.Variant. * * @param variant The GLib.Variant to deserialize * @return The deserialized PromptMessage * @throws Error If deserialization fails */ public PromptMessage.from_variant (Variant variant) throws Error { if (!variant.is_of_type (VariantType.VARDICT)) { throw new Mcp.Core.McpError.PARSE_ERROR ("PromptMessage must be a dictionary"); } if (variant.lookup_value ("role", null) == null) { throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing role in PromptMessage"); } if (variant.lookup_value ("content", null) == null) { throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing content in PromptMessage"); } this.role = variant.lookup_value ("role", VariantType.STRING).get_string (); var content = variant.lookup_value ("content", VariantType.VARDICT); // TODO: Determine content block type and deserialize appropriately // For now, assume TextContent if (content.lookup_value ("type", null) != null && content.lookup_value ("type", VariantType.STRING).get_string () == "text") { this.content = new Mcp.Types.Common.TextContent.from_variant (content); } else { throw new Mcp.Core.McpError.INVALID_REQUEST ("Unsupported content type in PromptMessage"); } } } }