| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792 |
- /*
- * 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
- */
- /**
- * Tool-related data types for MCP protocol.
- *
- * This namespace contains all tool-related types defined by the MCP specification,
- * including tool definitions, execution results, and related structures.
- */
- namespace Mcp.Tools.Types {
- /**
- * Tool definition as defined by MCP protocol.
- */
- public class ToolDefinition : GLib.Object {
- /**
- * Name of the tool.
- */
- public string name { get; set; }
-
- /**
- * Optional title of the tool.
- */
- public string? title { get; set; }
-
- /**
- * Optional description of the tool.
- */
- public string? description { get; set; }
-
- /**
- * JSON schema for tool input.
- */
- public Variant input_schema { get; set; }
-
- /**
- * Optional JSON schema for tool output.
- */
- public Variant? output_schema { get; set; }
-
- /**
- * Optional execution settings.
- */
- public ToolExecution? execution { get; set; }
-
- /**
- * Optional annotations for the tool.
- */
- public ToolAnnotations? annotations { get; set; }
-
- /**
- * Creates a new ToolDefinition.
- *
- * @param name Name of the tool
- * @param input_schema JSON schema for input
- */
- public ToolDefinition (string name, Variant input_schema) {
- this.name = name;
- this.input_schema = input_schema;
- }
-
- /**
- * Serializes ToolDefinition to GLib.Variant.
- *
- * @return A GLib.Variant representing this ToolDefinition
- */
- 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}", "inputSchema", input_schema);
-
- Mcp.Types.VariantUtils.add_variant_if_not_null (builder, "outputSchema", output_schema);
- Mcp.Types.VariantUtils.add_variant_if_not_null (builder, "execution",
- execution != null ? execution.to_variant () : null);
- Mcp.Types.VariantUtils.add_variant_if_not_null (builder, "annotations",
- annotations != null ? annotations.to_variant () : null);
-
- return builder.end ();
- }
-
- /**
- * Creates a ToolDefinition from GLib.Variant.
- *
- * @param variant The GLib.Variant to deserialize
- * @return The deserialized ToolDefinition
- * @throws Error If deserialization fails
- */
- public ToolDefinition.from_variant (Variant variant) throws Error {
- if (!variant.is_of_type (VariantType.VARDICT)) {
- throw new Mcp.Core.McpError.PARSE_ERROR ("ToolDefinition must be a dictionary");
- }
-
- if (variant.lookup_value ("name", null) == null) {
- throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing name in ToolDefinition");
- }
-
- if (variant.lookup_value ("inputSchema", null) == null) {
- throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing inputSchema in ToolDefinition");
- }
-
- 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.input_schema = variant.lookup_value ("inputSchema", VariantType.VARDICT);
-
- if (variant.lookup_value ("outputSchema", null) != null) {
- this.output_schema = variant.lookup_value ("outputSchema", VariantType.VARDICT);
- }
-
- if (variant.lookup_value ("execution", null) != null) {
- this.execution = new ToolExecution.from_variant (variant.lookup_value ("execution", VariantType.VARDICT));
- }
-
- if (variant.lookup_value ("annotations", null) != null) {
- this.annotations = new ToolAnnotations.from_variant (variant.lookup_value ("annotations", VariantType.VARDICT));
- }
- }
- }
-
- /**
- * Tool execution settings with enhanced context and state management.
- */
- public class ToolExecution : GLib.Object {
- /**
- * Task support level.
- */
- public string task_support { get; set; default = "forbidden"; }
-
- /**
- * Whether the tool supports progress reporting.
- */
- public bool supports_progress { get; set; default = false; }
-
- /**
- * Whether the tool supports cancellation.
- */
- public bool supports_cancellation { get; set; default = false; }
-
- /**
- * Maximum execution time in seconds (0 for no limit).
- */
- public int timeout_seconds { get; set; default = 30; }
-
- /**
- * Creates a new ToolExecution.
- *
- * @param task_support Task support level
- * @param supports_progress Whether progress reporting is supported
- * @param supports_cancellation Whether cancellation is supported
- * @param timeout_seconds Maximum execution time in seconds
- */
- public ToolExecution (string task_support = "forbidden",
- bool supports_progress = false,
- bool supports_cancellation = false,
- int timeout_seconds = 30) {
- this.task_support = task_support;
- this.supports_progress = supports_progress;
- this.supports_cancellation = supports_cancellation;
- this.timeout_seconds = timeout_seconds;
- }
-
- /**
- * Serializes ToolExecution to GLib.Variant.
- *
- * @return A GLib.Variant representing this ToolExecution
- */
- public Variant to_variant () {
- var builder = Mcp.Types.VariantUtils.new_dict_builder ();
- builder.add ("{sv}", "taskSupport", new Variant.string (task_support));
-
- if (supports_progress) {
- builder.add ("{sv}", "supportsProgress", new Variant.boolean (supports_progress));
- }
-
- if (supports_cancellation) {
- builder.add ("{sv}", "supportsCancellation", new Variant.boolean (supports_cancellation));
- }
-
- if (timeout_seconds > 0) {
- builder.add ("{sv}", "timeoutSeconds", new Variant.int32 (timeout_seconds));
- }
-
- return builder.end ();
- }
-
- /**
- * Creates a ToolExecution from GLib.Variant.
- *
- * @param variant The GLib.Variant to deserialize
- * @return The deserialized ToolExecution
- * @throws Error If deserialization fails
- */
- public ToolExecution.from_variant (Variant variant) throws Error {
- if (!variant.is_of_type (VariantType.VARDICT)) {
- throw new Mcp.Core.McpError.PARSE_ERROR ("ToolExecution must be a dictionary");
- }
-
- if (variant.lookup_value ("taskSupport", null) != null) {
- this.task_support = variant.lookup_value ("taskSupport", VariantType.STRING).get_string ();
- }
-
- if (variant.lookup_value ("supportsProgress", null) != null) {
- this.supports_progress = variant.lookup_value ("supportsProgress", VariantType.BOOLEAN).get_boolean ();
- }
-
- if (variant.lookup_value ("supportsCancellation", null) != null) {
- this.supports_cancellation = variant.lookup_value ("supportsCancellation", VariantType.BOOLEAN).get_boolean ();
- }
-
- if (variant.lookup_value ("timeoutSeconds", null) != null) {
- this.timeout_seconds = variant.lookup_value ("timeoutSeconds", VariantType.INT32).get_int32 ();
- }
- }
- }
-
- /**
- * Tool execution context for preserving state during execution.
- */
- public class ToolExecutionContext : GLib.Object {
- /**
- * Unique identifier for this execution context.
- */
- public string execution_id { get; set; }
-
- /**
- * The tool name being executed.
- */
- public string tool_name { get; set; }
-
- /**
- * The arguments passed to the tool.
- */
- public Variant arguments { get; set; }
-
- /**
- * Progress token for reporting progress.
- */
- public string? progress_token { get; set; }
-
- /**
- * Current execution state.
- */
- public ExecutionState state { get; set; default = ExecutionState.INITIALIZED; }
-
- /**
- * Timestamp when execution started.
- */
- public DateTime? start_time { get; set; }
-
- /**
- * Timestamp when execution ended.
- */
- public DateTime? end_time { get; set; }
-
- /**
- * Whether execution has been cancelled.
- */
- public bool is_cancelled { get; set; default = false; }
-
- /**
- * Cancellation source for async operations.
- */
- private GLib.Cancellable cancellable;
-
- /**
- * Creates a new ToolExecutionContext.
- *
- * @param execution_id Unique identifier for the execution
- * @param tool_name The tool name being executed
- * @param arguments The arguments passed to the tool
- * @param progress_token Optional progress token
- */
- public ToolExecutionContext (string execution_id, string tool_name,
- Variant arguments, string? progress_token = null) {
- this.execution_id = execution_id;
- this.tool_name = tool_name;
- this.arguments = arguments;
- this.progress_token = progress_token;
- this.cancellable = new GLib.Cancellable ();
- }
-
- /**
- * Gets the cancellable for this execution context.
- *
- * @return The cancellable object
- */
- public GLib.Cancellable get_cancellable () {
- return cancellable;
- }
-
- /**
- * Cancels the execution.
- */
- public void cancel () {
- is_cancelled = true;
- state = ExecutionState.CANCELLED;
- cancellable.cancel ();
- }
-
- /**
- * Marks the execution as started.
- */
- public void mark_started () {
- start_time = new DateTime.now_utc ();
- state = ExecutionState.RUNNING;
- }
-
- /**
- * Marks the execution as completed.
- */
- public void mark_completed () {
- end_time = new DateTime.now_utc ();
- if (state != ExecutionState.CANCELLED) {
- state = ExecutionState.COMPLETED;
- }
- }
-
- /**
- * Marks the execution as failed.
- */
- public void mark_failed () {
- end_time = new DateTime.now_utc ();
- state = ExecutionState.FAILED;
- }
-
- /**
- * Gets the execution duration in milliseconds.
- *
- * @return The duration in milliseconds, or 0 if not available
- */
- public int64 get_duration_ms () {
- if (start_time == null || end_time == null) {
- return 0;
- }
-
- return (int64) (end_time.difference (start_time) / 1000);
- }
- }
-
- /**
- * Execution states for tools.
- */
- public enum ExecutionState {
- /**
- * Execution has been initialized but not started.
- */
- INITIALIZED,
-
- /**
- * Execution is currently running.
- */
- RUNNING,
-
- /**
- * Execution completed successfully.
- */
- COMPLETED,
-
- /**
- * Execution failed.
- */
- FAILED,
-
- /**
- * Execution was cancelled.
- */
- CANCELLED
- }
-
- /**
- * Progress information for tool execution.
- */
- public class ToolProgress : GLib.Object {
- /**
- * Progress token identifying this progress update.
- */
- public string progress_token { get; set; }
-
- /**
- * Current progress value (0-100).
- */
- public double progress { get; set; }
-
- /**
- * Optional progress message.
- */
- public string? message { get; set; }
-
- /**
- * Creates a new ToolProgress.
- *
- * @param progress_token Progress token
- * @param progress Current progress value (0-100)
- * @param message Optional progress message
- */
- public ToolProgress (string progress_token, double progress, string? message = null) {
- this.progress_token = progress_token;
- this.progress = progress;
- this.message = message;
- }
-
- /**
- * Serializes ToolProgress to GLib.Variant.
- *
- * @return A GLib.Variant representing this ToolProgress
- */
- public Variant to_variant () {
- var builder = Mcp.Types.VariantUtils.new_dict_builder ();
- builder.add ("{sv}", "progressToken", new Variant.string (progress_token));
- builder.add ("{sv}", "progress", new Variant.double (progress));
-
- Mcp.Types.VariantUtils.add_string_if_not_null (builder, "message", message);
-
- return builder.end ();
- }
- }
-
- /**
- * Tool annotations.
- */
- public class ToolAnnotations : GLib.Object {
- /**
- * Optional audience for this tool.
- */
- public string? audience { get; set; }
-
- /**
- * Optional priority of this tool.
- */
- public double? priority { get; set; }
-
- /**
- * Creates a new ToolAnnotations.
- */
- public ToolAnnotations () {
- }
-
- /**
- * Serializes ToolAnnotations to GLib.Variant.
- *
- * @return A GLib.Variant representing this ToolAnnotations
- */
- public Variant to_variant () {
- var builder = Mcp.Types.VariantUtils.new_dict_builder ();
-
- Mcp.Types.VariantUtils.add_string_if_not_null (builder, "audience", audience);
-
- if (priority != null) {
- builder.add ("{sv}", "priority", new Variant.double (priority));
- }
-
- return builder.end ();
- }
-
- /**
- * Creates ToolAnnotations from GLib.Variant.
- *
- * @param variant The GLib.Variant to deserialize
- * @return The deserialized ToolAnnotations
- * @throws Error If deserialization fails
- */
- public ToolAnnotations.from_variant (Variant variant) throws Error {
- if (!variant.is_of_type (VariantType.VARDICT)) {
- throw new Mcp.Core.McpError.PARSE_ERROR ("ToolAnnotations must be a dictionary");
- }
-
- if (variant.lookup_value ("audience", null) != null) {
- this.audience = variant.lookup_value ("audience", VariantType.STRING).get_string ();
- }
-
- if (variant.lookup_value ("priority", null) != null) {
- this.priority = variant.lookup_value ("priority", VariantType.DOUBLE).get_double ();
- }
- }
- }
-
- /**
- * Result of calling a tool.
- */
- public class CallToolResult : GLib.Object {
- /**
- * List of content blocks in the result.
- */
- public Gee.ArrayList<Mcp.Types.Common.ContentBlock> content { get; set; }
-
- /**
- * Optional structured content data.
- * This field is used for structured data that doesn't fit into content blocks,
- * such as JSON objects, arrays, or other structured data formats.
- */
- public Variant? structured_content { get; set; }
-
- /**
- * Whether this result represents an error.
- */
- public bool is_error { get; set; default = false; }
-
- /**
- * Optional metadata about the result.
- */
- public Variant? metadata { get; set; }
-
- /**
- * Optional pagination cursor for results that support pagination.
- */
- public string? next_cursor { get; set; }
-
- /**
- * Creates a new CallToolResult.
- */
- public CallToolResult () {
- content = new Gee.ArrayList<Mcp.Types.Common.ContentBlock> ();
- }
-
- /**
- * Creates a new CallToolResult with content.
- *
- * @param content_blocks Initial content blocks
- * @param is_error Whether this result represents an error
- */
- public CallToolResult.with_content (Gee.ArrayList<Mcp.Types.Common.ContentBlock> content_blocks, bool is_error = false) {
- this.content = content_blocks;
- this.is_error = is_error;
- }
-
- /**
- * Creates a new CallToolResult with structured content.
- *
- * @param structured_data The structured content data
- * @param text_description Optional text description
- * @param is_error Whether this result represents an error
- */
- public CallToolResult.with_structured (Variant structured_data, string? text_description = null, bool is_error = false) {
- this.content = new Gee.ArrayList<Mcp.Types.Common.ContentBlock> ();
- this.structured_content = structured_data;
- this.is_error = is_error;
-
- if (text_description != null) {
- var text_content = new Mcp.Types.Common.TextContent (text_description);
- this.content.add (text_content);
- }
- }
-
- /**
- * Serializes CallToolResult to GLib.Variant.
- *
- * @return A GLib.Variant representing this CallToolResult
- */
- public Variant to_variant () {
- var builder = Mcp.Types.VariantUtils.new_dict_builder ();
-
- // Serialize content array
- var content_builder = Mcp.Types.VariantUtils.new_dict_array_builder ();
- foreach (var content_block in content) {
- content_builder.add_value (content_block.to_variant ());
- }
- builder.add ("{sv}", "content", content_builder.end ());
-
- // Add structured content if present
- Mcp.Types.VariantUtils.add_variant_if_not_null (builder, "structuredContent", structured_content);
-
- // Add error flag
- builder.add ("{sv}", "isError", new Variant.boolean (is_error));
-
- // Add metadata if present
- Mcp.Types.VariantUtils.add_variant_if_not_null (builder, "metadata", metadata);
-
- // Add pagination cursor if present
- Mcp.Types.VariantUtils.add_string_if_not_null (builder, "nextCursor", next_cursor);
-
- return builder.end ();
- }
-
- /**
- * Creates a CallToolResult from GLib.Variant.
- *
- * @param variant The GLib.Variant to deserialize
- * @return The deserialized CallToolResult
- * @throws Error If deserialization fails
- */
- public CallToolResult.from_variant (Variant variant) throws Error {
- if (!variant.is_of_type (VariantType.VARDICT)) {
- throw new Mcp.Core.McpError.PARSE_ERROR ("CallToolResult must be a dictionary");
- }
-
- if (variant.lookup_value ("content", null) == null) {
- throw new Mcp.Core.McpError.INVALID_REQUEST ("Missing content in CallToolResult");
- }
-
- this.content = new Gee.ArrayList<Mcp.Types.Common.ContentBlock> ();
-
- var content = variant.lookup_value ("content", new VariantType ("aa{sv}"));
-
- for (size_t i = 0; i < content.n_children (); i++) {
- var element = content.get_child_value (i);
- if (element.is_of_type (VariantType.VARDICT)) {
- var content_block = deserialize_content_block (element);
- if (content_block != null) {
- this.content.add (content_block);
- }
- }
- }
-
- // Parse structured content if present
- if (variant.lookup_value ("structuredContent", null) != null) {
- this.structured_content = variant.lookup_value ("structuredContent", null);
- }
-
- // Parse error flag if present
- if (variant.lookup_value ("isError", null) != null) {
- this.is_error = variant.lookup_value ("isError", VariantType.BOOLEAN).get_boolean ();
- }
-
- // Parse metadata if present
- if (variant.lookup_value ("metadata", null) != null) {
- this.metadata = variant.lookup_value ("metadata", null);
- }
-
- // Parse pagination cursor if present
- if (variant.lookup_value ("nextCursor", null) != null) {
- this.next_cursor = variant.lookup_value ("nextCursor", VariantType.STRING).get_string ();
- }
- }
-
- /**
- * Deserializes a content block from a Variant.
- *
- * @param variant The Variant to deserialize
- * @return The deserialized ContentBlock or null if type is unknown
- * @throws Error If deserialization fails
- */
- private Mcp.Types.Common.ContentBlock? deserialize_content_block (Variant variant) throws Error {
- if (!variant.is_of_type (VariantType.VARDICT)) {
- return null;
- }
-
- if (variant.lookup_value ("type", null) == null) {
- throw new Mcp.Core.McpError.INVALID_REQUEST ("Content block missing type field");
- }
-
- string type = variant.lookup_value ("type", VariantType.STRING).get_string ();
-
- switch (type) {
- case "text":
- return new Mcp.Types.Common.TextContent.from_variant (variant);
- case "image":
- return new Mcp.Types.Common.ImageContent.from_variant (variant);
- case "audio":
- return new Mcp.Types.Common.AudioContent.from_variant (variant);
- case "resource_link":
- return new Mcp.Types.Common.ResourceLink.from_variant (variant);
- case "resource":
- return new Mcp.Types.Common.EmbeddedResource.from_variant (variant);
- default:
- // Unknown content type, create a generic text content with warning
- return new Mcp.Types.Common.TextContent (
- "Warning: Unknown content type '%s'".printf (type)
- );
- }
- }
-
- /**
- * Adds a text content block to result.
- *
- * @param text The text content to add
- */
- public void add_text (string text) {
- var text_content = new Mcp.Types.Common.TextContent (text);
- content.add (text_content);
- }
-
- /**
- * Adds an image content block to result.
- *
- * @param data Base64 encoded image data
- * @param mime_type MIME type of image
- */
- public void add_image (string data, string mime_type) {
- var image_content = new Mcp.Types.Common.ImageContent (data, mime_type);
- content.add (image_content);
- }
-
- /**
- * Adds a resource link to result.
- *
- * @param uri URI of resource
- * @param name Name of resource
- */
- public void add_resource_link (string uri, string name) {
- var resource_link = new Mcp.Types.Common.ResourceLink (uri, name);
- content.add (resource_link);
- }
-
- /**
- * Sets structured content and optionally adds a text description.
- *
- * @param structured_data The structured content data
- * @param description Optional text description
- */
- public void update_structured_content (Variant structured_data, string? description = null) {
- this.structured_content = structured_data;
-
- if (description != null) {
- add_text (description);
- }
- }
-
- /**
- * Sets metadata for result.
- *
- * @param metadata The metadata to set
- */
- public void update_metadata (Variant metadata) {
- this.metadata = metadata;
- }
-
- /**
- * Sets pagination cursor for result.
- *
- * @param cursor The pagination cursor
- */
- public void update_next_cursor (string cursor) {
- this.next_cursor = cursor;
- }
-
- /**
- * Creates a successful result with text content.
- *
- * @param text The text content
- * @return A successful CallToolResult
- */
- public static CallToolResult success (string text) {
- var result = new CallToolResult ();
- result.add_text (text);
- return result;
- }
-
- /**
- * Creates an error result with text content.
- *
- * @param error_message The error message
- * @return An error CallToolResult
- */
- public static CallToolResult error (string error_message) {
- var result = new CallToolResult ();
- result.add_text (error_message);
- result.is_error = true;
- return result;
- }
-
- /**
- * Creates a successful result with structured content.
- *
- * @param structured_data The structured content data
- * @param description Optional text description
- * @return A successful CallToolResult with structured content
- */
- public static CallToolResult success_structured (Variant structured_data, string? description = null) {
- var result = new CallToolResult ();
- result.update_structured_content (structured_data, description);
- return result;
- }
- }
- }
|