|
@@ -53,11 +53,11 @@ namespace Mcp.Prompts {
|
|
|
*/
|
|
*/
|
|
|
public void register_template (string name, Template template) throws Error {
|
|
public void register_template (string name, Template template) throws Error {
|
|
|
if (name == null || name.strip () == "") {
|
|
if (name == null || name.strip () == "") {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt name cannot be empty");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt name cannot be empty or null. Please provide a valid name for the prompt template.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (templates.contains (name)) {
|
|
if (templates.contains (name)) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt already registered: %s".printf (name));
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt '%s' is already registered. Use a different name or unregister the existing prompt first.".printf (name));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
templates.insert (name, template);
|
|
templates.insert (name, template);
|
|
@@ -72,7 +72,7 @@ namespace Mcp.Prompts {
|
|
|
*/
|
|
*/
|
|
|
public void unregister_template (string name) throws Error {
|
|
public void unregister_template (string name) throws Error {
|
|
|
if (!templates.contains (name)) {
|
|
if (!templates.contains (name)) {
|
|
|
- throw new Mcp.Core.McpError.PROMPT_NOT_FOUND ("Prompt not found: %s".printf (name));
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt '%s' not found. Cannot unregister a prompt that doesn't exist. Check the name and try again.".printf (name));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
templates.remove (name);
|
|
templates.remove (name);
|
|
@@ -129,30 +129,70 @@ namespace Mcp.Prompts {
|
|
|
* @throws Error If handling fails
|
|
* @throws Error If handling fails
|
|
|
*/
|
|
*/
|
|
|
public async Variant handle_list (Variant @params) throws Error {
|
|
public async Variant handle_list (Variant @params) throws Error {
|
|
|
- var result = new Gee.ArrayList<Mcp.Prompts.Types.PromptDefinition> ();
|
|
|
|
|
|
|
+ // Extract cursor parameter if present
|
|
|
|
|
+ string? cursor = null;
|
|
|
|
|
+ if (@params.lookup_value ("cursor", null) != null) {
|
|
|
|
|
+ cursor = @params.lookup_value ("cursor", VariantType.STRING).get_string ();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Get prompt definitions from all templates
|
|
|
|
|
|
|
+ // Get all prompt definitions from all templates
|
|
|
|
|
+ var all_prompts = new Gee.ArrayList<Mcp.Prompts.Types.PromptDefinition> ();
|
|
|
foreach (var name in templates.get_keys ()) {
|
|
foreach (var name in templates.get_keys ()) {
|
|
|
var template = templates.lookup (name);
|
|
var template = templates.lookup (name);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
var definition = template.get_definition ();
|
|
var definition = template.get_definition ();
|
|
|
- result.add (definition);
|
|
|
|
|
|
|
+ all_prompts.add (definition);
|
|
|
} catch (Error e) {
|
|
} catch (Error e) {
|
|
|
// Continue with other templates
|
|
// Continue with other templates
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Sort prompts by name for consistent pagination
|
|
|
|
|
+ all_prompts.sort ((a, b) => {
|
|
|
|
|
+ return strcmp (a.name, b.name);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Pagination settings
|
|
|
|
|
+ const int PAGE_SIZE = 10;
|
|
|
|
|
+ int start_index = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // Parse cursor to determine starting position
|
|
|
|
|
+ if (cursor != null) {
|
|
|
|
|
+ // Simple cursor implementation: cursor is the page number as a string
|
|
|
|
|
+ // Default to 0 if parsing fails
|
|
|
|
|
+ start_index = int.parse (cursor) * PAGE_SIZE;
|
|
|
|
|
+ if (start_index < 0) {
|
|
|
|
|
+ start_index = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate the end index for this page
|
|
|
|
|
+ int end_index = int.min (start_index + PAGE_SIZE, all_prompts.size);
|
|
|
|
|
+
|
|
|
|
|
+ // Get the prompts for this page
|
|
|
|
|
+ var page_prompts = new Gee.ArrayList<Mcp.Prompts.Types.PromptDefinition> ();
|
|
|
|
|
+ for (int i = start_index; i < end_index; i++) {
|
|
|
|
|
+ page_prompts.add (all_prompts[i]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Build response as Variant using utility functions
|
|
// Build response as Variant using utility functions
|
|
|
var result_builder = Mcp.Types.VariantUtils.new_dict_builder ();
|
|
var result_builder = Mcp.Types.VariantUtils.new_dict_builder ();
|
|
|
|
|
|
|
|
// Serialize prompts array
|
|
// Serialize prompts array
|
|
|
var prompts_builder = Mcp.Types.VariantUtils.new_dict_array_builder ();
|
|
var prompts_builder = Mcp.Types.VariantUtils.new_dict_array_builder ();
|
|
|
- foreach (var prompt in result) {
|
|
|
|
|
|
|
+ foreach (var prompt in page_prompts) {
|
|
|
prompts_builder.add_value (prompt.to_variant ());
|
|
prompts_builder.add_value (prompt.to_variant ());
|
|
|
}
|
|
}
|
|
|
result_builder.add ("{sv}", "prompts", prompts_builder.end ());
|
|
result_builder.add ("{sv}", "prompts", prompts_builder.end ());
|
|
|
|
|
|
|
|
|
|
+ // Add nextCursor if there are more prompts
|
|
|
|
|
+ if (end_index < all_prompts.size) {
|
|
|
|
|
+ // Next cursor is the next page number
|
|
|
|
|
+ int next_page = start_index / PAGE_SIZE + 1;
|
|
|
|
|
+ result_builder.add ("{sv}", "nextCursor", new Variant.string (next_page.to_string ()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return result_builder.end ();
|
|
return result_builder.end ();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -165,11 +205,15 @@ namespace Mcp.Prompts {
|
|
|
*/
|
|
*/
|
|
|
public async Variant handle_get (Variant @params) throws Error {
|
|
public async Variant handle_get (Variant @params) throws Error {
|
|
|
if (@params.lookup_value ("name", null) == null) {
|
|
if (@params.lookup_value ("name", null) == null) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Missing name parameter");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Missing required 'name' parameter. The prompts/get method requires a prompt name to retrieve.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
string name = @params.lookup_value ("name", VariantType.STRING).get_string ();
|
|
string name = @params.lookup_value ("name", VariantType.STRING).get_string ();
|
|
|
|
|
|
|
|
|
|
+ if (name.strip () == "") {
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("The 'name' parameter cannot be empty. Please provide a valid prompt name.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
Variant? arguments = null;
|
|
Variant? arguments = null;
|
|
|
if (@params.lookup_value ("arguments", null) != null) {
|
|
if (@params.lookup_value ("arguments", null) != null) {
|
|
|
arguments = @params.lookup_value ("arguments", VariantType.VARDICT);
|
|
arguments = @params.lookup_value ("arguments", VariantType.VARDICT);
|
|
@@ -177,14 +221,14 @@ namespace Mcp.Prompts {
|
|
|
|
|
|
|
|
Template? template = templates.lookup (name);
|
|
Template? template = templates.lookup (name);
|
|
|
if (template == null) {
|
|
if (template == null) {
|
|
|
- throw new Mcp.Core.McpError.PROMPT_NOT_FOUND ("Prompt not found: %s".printf (name));
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Prompt '%s' not found. Verify the prompt name is correct and that it has been registered.".printf (name));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
var result = yield template.get_prompt (arguments);
|
|
var result = yield template.get_prompt (arguments);
|
|
|
return result.to_variant ();
|
|
return result.to_variant ();
|
|
|
} catch (Error e) {
|
|
} catch (Error e) {
|
|
|
- throw e;
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INTERNAL_ERROR ("Failed to generate prompt '%s': %s".printf (name, e.message));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -206,17 +250,17 @@ namespace Mcp.Prompts {
|
|
|
*/
|
|
*/
|
|
|
private void validate_template (Template template) throws Error {
|
|
private void validate_template (Template template) throws Error {
|
|
|
if (template == null) {
|
|
if (template == null) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Template cannot be null");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Template cannot be null. Please provide a valid Template instance.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
var definition = template.get_definition ();
|
|
var definition = template.get_definition ();
|
|
|
if (definition == null) {
|
|
if (definition == null) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Template definition cannot be null");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Template definition cannot be null. The template must return a valid PromptDefinition.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (definition.name == null || definition.name.strip () == "") {
|
|
if (definition.name == null || definition.name.strip () == "") {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Template name cannot be empty");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Template name cannot be empty or null. Please provide a valid name for the prompt template.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Validate arguments
|
|
// Validate arguments
|
|
@@ -224,18 +268,18 @@ namespace Mcp.Prompts {
|
|
|
var argument_names = new Gee.HashSet<string> ();
|
|
var argument_names = new Gee.HashSet<string> ();
|
|
|
foreach (var arg in definition.arguments) {
|
|
foreach (var arg in definition.arguments) {
|
|
|
if (arg.name == null || arg.name.strip () == "") {
|
|
if (arg.name == null || arg.name.strip () == "") {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Argument name cannot be empty");
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Argument name cannot be empty or null. All arguments must have valid names.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (argument_names.contains (arg.name)) {
|
|
if (argument_names.contains (arg.name)) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Duplicate argument name: %s".printf (arg.name));
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Duplicate argument name '%s'. Each argument must have a unique name.".printf (arg.name));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
argument_names.add (arg.name);
|
|
argument_names.add (arg.name);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
} catch (Error e) {
|
|
} catch (Error e) {
|
|
|
- throw new Mcp.Core.McpError.INVALID_PARAMS ("Template validation failed: %s".printf (e.message));
|
|
|
|
|
|
|
+ throw new Mcp.Core.McpError.INVALID_PARAMS ("Template validation failed: %s. Please check the template implementation and fix any issues.".printf (e.message));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|