diff --git a/src/tools/auth.ts b/src/tools/auth.ts index 0828c64..d5024b8 100644 --- a/src/tools/auth.ts +++ b/src/tools/auth.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { AuthMethod } from "@/types/client.js"; import { getErrorMessage } from "@/utils/error.js"; @@ -14,14 +15,7 @@ export class AuthTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ @@ -35,42 +29,48 @@ export class AuthTools { "• Verify setup: Use this after configuring new credentials\n" + "• Troubleshoot: Run when experiencing connection issues\n" + "• Health check: Regular verification of WordPress connectivity", - parameters: [], // The 'site' parameter is added dynamically by the server + // The 'site' parameter is added dynamically by the server + inputSchema: { + type: "object", + properties: {}, + }, handler: this.handleTestAuth.bind(this), }, { name: "wp_get_auth_status", description: "Gets the current authentication status for a configured WordPress site.", - parameters: [], + inputSchema: { + type: "object", + properties: {}, + }, handler: this.handleGetAuthStatus.bind(this), }, { name: "wp_switch_auth_method", description: "Switches the authentication method for a site for the current session.", - parameters: [ - { - name: "method", - type: "string", - required: true, - description: "The new authentication method to use.", - enum: ["app-password", "jwt", "basic", "api-key", "cookie"], + inputSchema: { + type: "object", + properties: { + method: { + type: "string", + description: "The new authentication method to use.", + enum: ["app-password", "jwt", "basic", "api-key", "cookie"], + }, + username: { + type: "string", + description: "The username for 'app-password' or 'basic' authentication.", + }, + password: { + type: "string", + description: "The Application Password for 'app-password' or password for 'basic' auth.", + }, + jwt_token: { + type: "string", + description: "The token for 'jwt' authentication.", + }, }, - { - name: "username", - type: "string", - description: "The username for 'app-password' or 'basic' authentication.", - }, - { - name: "password", - type: "string", - description: "The Application Password for 'app-password' or password for 'basic' auth.", - }, - { - name: "jwt_token", - type: "string", - description: "The token for 'jwt' authentication.", - }, - ], + required: ["method"], + }, handler: this.handleSwitchAuthMethod.bind(this), }, ]; diff --git a/src/tools/comments.ts b/src/tools/comments.ts index 91e6591..ab0ef42 100644 --- a/src/tools/comments.ts +++ b/src/tools/comments.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import { MCPToolSchema } from "@/types/mcp.js"; import { CommentQueryParams, CreateCommentRequest, UpdateCommentRequest } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; import { toolParams } from "./params.js"; @@ -15,143 +16,142 @@ export class CommentTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ { name: "wp_list_comments", description: "Lists comments from a WordPress site, with filters.", - parameters: [ - { - name: "post", - type: "number", - description: "Limit results to comments assigned to a specific post ID.", + inputSchema: { + type: "object", + properties: { + post: { + type: "number", + description: "Limit results to comments assigned to a specific post ID.", + }, + status: { + type: "string", + description: "Filter by comment status.", + enum: ["hold", "approve", "spam", "trash"], + }, }, - { - name: "status", - type: "string", - description: "Filter by comment status.", - enum: ["hold", "approve", "spam", "trash"], - }, - ], + }, handler: this.handleListComments.bind(this), }, { name: "wp_get_comment", description: "Retrieves a single comment by its ID.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the comment.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the comment.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetComment.bind(this), }, { name: "wp_create_comment", description: "Creates a new comment on a post.", - parameters: [ - { - name: "post", - type: "number", - required: true, - description: "The ID of the post to comment on.", - }, - { - name: "content", - type: "string", - required: true, - description: "The content of the comment.", - }, - { - name: "author_name", - type: "string", - description: "The name of the comment author.", - }, - { - name: "author_email", - type: "string", - description: "The email of the comment author.", + inputSchema: { + type: "object", + properties: { + post: { + type: "number", + description: "The ID of the post to comment on.", + }, + content: { + type: "string", + description: "The content of the comment.", + }, + author_name: { + type: "string", + description: "The name of the comment author.", + }, + author_email: { + type: "string", + description: "The email of the comment author.", + }, }, - ], + required: ["post", "content"], + }, handler: this.handleCreateComment.bind(this), }, { name: "wp_update_comment", description: "Updates an existing comment.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the comment to update.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the comment to update.", + }, + content: { + type: "string", + description: "The updated content for the comment.", + }, + status: { + type: "string", + description: "The new status for the comment.", + enum: ["hold", "approve", "spam", "trash"], + }, }, - { - name: "content", - type: "string", - description: "The updated content for the comment.", - }, - { - name: "status", - type: "string", - description: "The new status for the comment.", - enum: ["hold", "approve", "spam", "trash"], - }, - ], + required: ["id"], + }, handler: this.handleUpdateComment.bind(this), }, { name: "wp_delete_comment", description: "Deletes a comment.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the comment to delete.", - }, - { - name: "force", - type: "boolean", - description: "If true, the comment will be permanently deleted. Defaults to false (moved to trash).", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the comment to delete.", + }, + force: { + type: "boolean", + description: "If true, the comment will be permanently deleted. Defaults to false (moved to trash).", + }, }, - ], + required: ["id"], + }, handler: this.handleDeleteComment.bind(this), }, { name: "wp_approve_comment", description: "Approves a pending comment.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the comment to approve.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the comment to approve.", + }, }, - ], + required: ["id"], + }, handler: this.handleApproveComment.bind(this), }, { name: "wp_spam_comment", description: "Marks a comment as spam.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the comment to mark as spam.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the comment to mark as spam.", + }, }, - ], + required: ["id"], + }, handler: this.handleSpamComment.bind(this), }, ]; diff --git a/src/tools/media.ts b/src/tools/media.ts index b845c10..cf8a898 100644 --- a/src/tools/media.ts +++ b/src/tools/media.ts @@ -1,5 +1,6 @@ import * as fs from "fs"; import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { MediaQueryParams, UpdateMediaRequest, UploadMediaRequest } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; import { toolParams } from "./params.js"; @@ -55,140 +56,131 @@ export class MediaTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ { name: "wp_list_media", description: "Lists media items from a WordPress site, with filters.", - parameters: [ - { - name: "per_page", - type: "number", - description: "Number of items to return per page (max 100).", + inputSchema: { + type: "object", + properties: { + per_page: { + type: "number", + description: "Number of items to return per page (max 100).", + }, + search: { + type: "string", + description: "Limit results to those matching a search term.", + }, + media_type: { + type: "string", + description: "Limit results to a specific media type.", + enum: ["image", "video", "audio", "application"], + }, }, - { - name: "search", - type: "string", - description: "Limit results to those matching a search term.", - }, - { - name: "media_type", - type: "string", - description: "Limit results to a specific media type.", - enum: ["image", "video", "audio", "application"], - }, - ], + }, handler: this.handleListMedia.bind(this), }, { name: "wp_get_media", description: "Retrieves a single media item by its ID.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the media item.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the media item.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetMedia.bind(this), }, { name: "wp_upload_media", description: "Uploads a file to the WordPress media library.", - parameters: [ - { - name: "file_path", - type: "string", - required: true, - description: "The local, absolute path to the file to upload.", - }, - { - name: "title", - type: "string", - description: "The title for the media item.", - }, - { - name: "alt_text", - type: "string", - description: "Alternative text for the media item (for accessibility).", - }, - { - name: "caption", - type: "string", - description: "The caption for the media item.", - }, - { - name: "description", - type: "string", - description: "The description for the media item.", + inputSchema: { + type: "object", + properties: { + file_path: { + type: "string", + description: "The local, absolute path to the file to upload.", + }, + title: { + type: "string", + description: "The title for the media item.", + }, + alt_text: { + type: "string", + description: "Alternative text for the media item (for accessibility).", + }, + caption: { + type: "string", + description: "The caption for the media item.", + }, + description: { + type: "string", + description: "The description for the media item.", + }, + post: { + type: "number", + description: "The ID of a post to attach this media to.", + }, }, - { - name: "post", - type: "number", - description: "The ID of a post to attach this media to.", - }, - ], + required: ["file_path"], + }, handler: this.handleUploadMedia.bind(this), }, { name: "wp_update_media", description: "Updates the metadata of an existing media item.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the media item to update.", - }, - { - name: "title", - type: "string", - description: "The new title for the media item.", - }, - { - name: "alt_text", - type: "string", - description: "The new alternative text.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the media item to update.", + }, + title: { + type: "string", + description: "The new title for the media item.", + }, + alt_text: { + type: "string", + description: "The new alternative text.", + }, + caption: { + type: "string", + description: "The new caption.", + }, + description: { + type: "string", + description: "The new description.", + }, }, - { - name: "caption", - type: "string", - description: "The new caption.", - }, - { - name: "description", - type: "string", - description: "The new description.", - }, - ], + required: ["id"], + }, handler: this.handleUpdateMedia.bind(this), }, { name: "wp_delete_media", description: "Deletes a media item.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the media item to delete.", - }, - { - name: "force", - type: "boolean", - description: "If true, permanently delete. If false, move to trash. Defaults to false.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the media item to delete.", + }, + force: { + type: "boolean", + description: "If true, permanently delete. If false, move to trash. Defaults to false.", + }, }, - ], + required: ["id"], + }, handler: this.handleDeleteMedia.bind(this), }, ]; diff --git a/src/tools/pages.ts b/src/tools/pages.ts index 0ed791e..2f0cb23 100644 --- a/src/tools/pages.ts +++ b/src/tools/pages.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { CreatePageRequest, PostQueryParams as PageQueryParams, UpdatePageRequest } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; import { toolParams } from "./params.js"; @@ -15,140 +16,137 @@ export class PageTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ { name: "wp_list_pages", description: "Lists pages from a WordPress site, with filters.", - parameters: [ - { - name: "per_page", - type: "number", - description: "Number of items to return per page (max 100).", + inputSchema: { + type: "object", + properties: { + per_page: { + type: "number", + description: "Number of items to return per page (max 100).", + }, + search: { + type: "string", + description: "Limit results to those matching a search term.", + }, + status: { + type: "string", + description: "Filter by page status.", + enum: ["publish", "future", "draft", "pending", "private"], + }, }, - { - name: "search", - type: "string", - description: "Limit results to those matching a search term.", - }, - { - name: "status", - type: "string", - description: "Filter by page status.", - enum: ["publish", "future", "draft", "pending", "private"], - }, - ], + required: [], + }, handler: this.handleListPages.bind(this), }, { name: "wp_get_page", description: "Retrieves a single page by its ID, optionally including full content for editing.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the page.", - }, - { - name: "include_content", - type: "boolean", - description: "If true, includes the full HTML content of the page. Default: false", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the page.", + }, + include_content: { + type: "boolean", + description: "If true, includes the full HTML content of the page. Default: false", + }, }, - ], + required: ["id"], + }, handler: this.handleGetPage.bind(this), }, { name: "wp_create_page", description: "Creates a new page.", - parameters: [ - { - name: "title", - type: "string", - required: true, - description: "The title for the page.", - }, - { - name: "content", - type: "string", - description: "The content for the page, in HTML format.", - }, - { - name: "status", - type: "string", - description: "The publishing status for the page.", - enum: ["publish", "draft", "pending", "private"], + inputSchema: { + type: "object", + properties: { + title: { + type: "string", + description: "The title for the page.", + }, + content: { + type: "string", + description: "The content for the page, in HTML format.", + }, + status: { + type: "string", + description: "The publishing status for the page.", + enum: ["publish", "draft", "pending", "private"], + }, }, - ], + required: ["title"], + }, handler: this.handleCreatePage.bind(this), }, { name: "wp_update_page", description: "Updates an existing page.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the page to update.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the page to update.", + }, + title: { + type: "string", + description: "The new title for the page.", + }, + content: { + type: "string", + description: "The new content for the page, in HTML format.", + }, + status: { + type: "string", + description: "The new status for the page.", + enum: ["publish", "draft", "pending", "private"], + }, }, - { - name: "title", - type: "string", - description: "The new title for the page.", - }, - { - name: "content", - type: "string", - description: "The new content for the page, in HTML format.", - }, - { - name: "status", - type: "string", - description: "The new status for the page.", - enum: ["publish", "draft", "pending", "private"], - }, - ], + required: ["id"], + }, handler: this.handleUpdatePage.bind(this), }, { name: "wp_delete_page", description: "Deletes a page.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the page to delete.", - }, - { - name: "force", - type: "boolean", - description: "If true, permanently delete. If false, move to trash. Defaults to false.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the page to delete.", + }, + force: { + type: "boolean", + description: "If true, permanently delete. If false, move to trash. Defaults to false.", + }, }, - ], + required: ["id"], + }, handler: this.handleDeletePage.bind(this), }, { name: "wp_get_page_revisions", description: "Retrieves revisions for a specific page.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the page to get revisions for.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the page to get revisions for.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetPageRevisions.bind(this), }, ]; diff --git a/src/tools/site.ts b/src/tools/site.ts index 1a34517..b5cc3ac 100644 --- a/src/tools/site.ts +++ b/src/tools/site.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { WordPressApplicationPassword } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; @@ -14,43 +15,39 @@ export class SiteTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ { name: "wp_get_site_settings", description: "Retrieves the general settings for a WordPress site.", - parameters: [], + inputSchema: { + type: "object", + properties: {}, + }, handler: this.handleGetSiteSettings.bind(this), }, { name: "wp_update_site_settings", description: "Updates one or more general settings for a WordPress site.", - parameters: [ - { - name: "title", - type: "string", - description: "The title of the site.", + inputSchema: { + type: "object", + properties: { + title: { + type: "string", + description: "The title of the site.", + }, + description: { + type: "string", + description: "The tagline or description of the site.", + }, + timezone: { + type: "string", + description: "A city in the same timezone, e.g., 'America/New_York'.", + }, }, - { - name: "description", - type: "string", - description: "The tagline or description of the site.", - }, - { - name: "timezone", - type: "string", - description: "A city in the same timezone, e.g., 'America/New_York'.", - }, - ], + }, handler: this.handleUpdateSiteSettings.bind(this), }, { @@ -63,71 +60,74 @@ export class SiteTools { '• Search pages: `wp_search_site --term="about" --type="pages"`\n' + '• Search media: `wp_search_site --term="logo" --type="media"`\n' + '• Find specific content: `wp_search_site --term="contact form"`', - parameters: [ - { - name: "term", - type: "string", - required: true, - description: "The search term to look for.", - }, - { - name: "type", - type: "string", - description: "The type of content to search.", - enum: ["posts", "pages", "media"], + inputSchema: { + type: "object", + properties: { + term: { + type: "string", + description: "The search term to look for.", + }, + type: { + type: "string", + description: "The type of content to search.", + enum: ["posts", "pages", "media"], + }, }, - ], + required: ["term"], + }, handler: this.handleSearchSite.bind(this), }, { name: "wp_get_application_passwords", description: "Lists application passwords for a specific user.", - parameters: [ - { - name: "user_id", - type: "number", - required: true, - description: "The ID of the user to get application passwords for.", + inputSchema: { + type: "object", + properties: { + user_id: { + type: "number", + description: "The ID of the user to get application passwords for.", + }, }, - ], + required: ["user_id"], + }, handler: this.handleGetApplicationPasswords.bind(this), }, { name: "wp_create_application_password", description: "Creates a new application password for a user.", - parameters: [ - { - name: "user_id", - type: "number", - required: true, - description: "The ID of the user to create the password for.", + inputSchema: { + type: "object", + properties: { + user_id: { + type: "number", + description: "The ID of the user to create the password for.", + }, + app_name: { + type: "string", + description: "The name of the application this password is for.", + }, }, - { - name: "app_name", - type: "string", - required: true, - description: "The name of the application this password is for.", - }, - ], + required: ["user_id", "app_name"], + }, handler: this.handleCreateApplicationPassword.bind(this), }, { name: "wp_delete_application_password", description: "Revokes an existing application password.", - parameters: [ - { - name: "user_id", - type: "number", - required: true, - description: "The ID of the user who owns the password.", - }, - { - name: "uuid", - type: "string", - required: true, - description: "The UUID of the application password to revoke.", + inputSchema: { + type: "object", + properties: { + user_id: { + type: "number", + description: "The ID of the user who owns the password.", + }, + uuid: { + type: "string", + description: "The UUID of the application password to revoke.", + }, }, - ], + required: ["user_id", "uuid"], + }, handler: this.handleDeleteApplicationPassword.bind(this), }, ]; diff --git a/src/tools/taxonomies.ts b/src/tools/taxonomies.ts index a482d8e..0170ba3 100644 --- a/src/tools/taxonomies.ts +++ b/src/tools/taxonomies.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { CreateCategoryRequest, CreateTagRequest, UpdateCategoryRequest, UpdateTagRequest } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; import { toolParams } from "./params.js"; @@ -15,14 +16,7 @@ export class TaxonomyTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ @@ -30,150 +24,166 @@ export class TaxonomyTools { { name: "wp_list_categories", description: "Lists categories from a WordPress site.", - parameters: [ - { - name: "search", - type: "string", - description: "Limit results to those matching a search term.", + inputSchema: { + type: "object", + properties: { + search: { + type: "string", + description: "Limit results to those matching a search term.", + }, + hide_empty: { + type: "boolean", + description: "Whether to hide categories with no posts.", + }, }, - { - name: "hide_empty", - type: "boolean", - description: "Whether to hide categories with no posts.", - }, - ], + }, handler: this.handleListCategories.bind(this), }, { name: "wp_get_category", description: "Retrieves a single category by its ID.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the category.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the category.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetCategory.bind(this), }, { name: "wp_create_category", description: "Creates a new category.", - parameters: [ - { - name: "name", - type: "string", - required: true, - description: "The name of the category.", - }, - { - name: "description", - type: "string", - description: "The description for the category.", + inputSchema: { + type: "object", + properties: { + name: { + type: "string", + description: "The name of the category.", + }, + description: { + type: "string", + description: "The description for the category.", + }, }, - ], + required: ["name"], + }, handler: this.handleCreateCategory.bind(this), }, { name: "wp_update_category", description: "Updates an existing category.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the category to update.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the category to update.", + }, + name: { + type: "string", + description: "The new name for the category.", + }, }, - { - name: "name", - type: "string", - description: "The new name for the category.", - }, - ], + required: ["id"], + }, handler: this.handleUpdateCategory.bind(this), }, { name: "wp_delete_category", description: "Deletes a category.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the category to delete.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the category to delete.", + }, }, - ], + required: ["id"], + }, handler: this.handleDeleteCategory.bind(this), }, // Tags { name: "wp_list_tags", description: "Lists tags from a WordPress site.", - parameters: [ - { - name: "search", - type: "string", - description: "Limit results to those matching a search term.", + inputSchema: { + type: "object", + properties: { + search: { + type: "string", + description: "Limit results to those matching a search term.", + }, }, - ], + }, handler: this.handleListTags.bind(this), }, { name: "wp_get_tag", description: "Retrieves a single tag by its ID.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the tag.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the tag.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetTag.bind(this), }, { name: "wp_create_tag", description: "Creates a new tag.", - parameters: [ - { - name: "name", - type: "string", - required: true, - description: "The name of the tag.", + inputSchema: { + type: "object", + properties: { + name: { + type: "string", + description: "The name of the tag.", + }, }, - ], + required: ["name"], + }, handler: this.handleCreateTag.bind(this), }, { name: "wp_update_tag", description: "Updates an existing tag.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the tag to update.", - }, - { - name: "name", - type: "string", - description: "The new name for the tag.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the tag to update.", + }, + name: { + type: "string", + description: "The new name for the tag.", + }, }, - ], + required: ["id"], + }, handler: this.handleUpdateTag.bind(this), }, { name: "wp_delete_tag", description: "Deletes a tag.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the tag to delete.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the tag to delete.", + }, }, - ], + required: ["id"], + }, handler: this.handleDeleteTag.bind(this), }, ]; diff --git a/src/tools/users.ts b/src/tools/users.ts index 7d50cfa..12b0787 100644 --- a/src/tools/users.ts +++ b/src/tools/users.ts @@ -1,4 +1,5 @@ import { WordPressClient } from "@/client/api.js"; +import type { MCPToolSchema } from "@/types/mcp.js"; import { CreateUserRequest, UpdateUserRequest, UserQueryParams } from "@/types/wordpress.js"; import { getErrorMessage } from "@/utils/error.js"; import { WordPressDataStreamer, StreamingUtils, StreamingResult } from "@/utils/streaming.js"; @@ -16,14 +17,7 @@ export class UserTools { public getTools(): Array<{ name: string; description: string; - parameters?: Array<{ - name: string; - type?: string; - description?: string; - required?: boolean; - enum?: string[]; - items?: unknown; - }>; + inputSchema?: MCPToolSchema; handler: (client: WordPressClient, params: Record) => Promise; }> { return [ @@ -37,32 +31,35 @@ export class UserTools { '• Filter by role: `wp_list_users --roles=["editor","author"]`\n' + '• Find admins: `wp_list_users --roles=["administrator"]`\n' + '• Combined search: `wp_list_users --search="smith" --roles=["subscriber"]`', - parameters: [ - { - name: "search", - type: "string", - description: "Limit results to those matching a search term.", + inputSchema: { + type: "object", + properties: { + search: { + type: "string", + description: "Limit results to those matching a search term.", + }, + roles: { + type: "array", + items: { type: "string" }, + description: "Limit results to users with specific roles.", + }, }, - { - name: "roles", - type: "array", - items: { type: "string" }, - description: "Limit results to users with specific roles.", - }, - ], + }, handler: this.handleListUsers.bind(this), }, { name: "wp_get_user", description: "Retrieves a single user by their ID.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The unique identifier for the user.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The unique identifier for the user.", + }, }, - ], + required: ["id"], + }, handler: this.handleGetUser.bind(this), }, { @@ -74,79 +71,80 @@ export class UserTools { "• Check permissions: Use this to verify your current user's capabilities and roles\n" + "• Account verification: Confirm you're authenticated with the correct account\n" + "• Profile details: View registration date, email, and user metadata", - parameters: [], + inputSchema: { + type: "object", + properties: {}, + }, handler: this.handleGetCurrentUser.bind(this), }, { name: "wp_create_user", description: "Creates a new user.", - parameters: [ - { - name: "username", - type: "string", - required: true, - description: "The username for the new user.", - }, - { - name: "email", - type: "string", - required: true, - description: "The email address for the new user.", - }, - { - name: "password", - type: "string", - required: true, - description: "The password for the new user.", - }, - { - name: "roles", - type: "array", - items: { type: "string" }, - description: "An array of roles to assign to the user.", + inputSchema: { + type: "object", + properties: { + username: { + type: "string", + description: "The username for the new user.", + }, + email: { + type: "string", + description: "The email address for the new user.", + }, + password: { + type: "string", + description: "The password for the new user.", + }, + roles: { + type: "array", + items: { type: "string" }, + description: "An array of roles to assign to the user.", + }, }, - ], + required: ["username", "email", "password"], + }, handler: this.handleCreateUser.bind(this), }, { name: "wp_update_user", description: "Updates an existing user.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the user to update.", - }, - { - name: "email", - type: "string", - description: "The new email address for the user.", - }, - { - name: "name", - type: "string", - description: "The new display name for the user.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the user to update.", + }, + email: { + type: "string", + description: "The new email address for the user.", + }, + name: { + type: "string", + description: "The new display name for the user.", + }, }, - ], + required: ["id"], + }, handler: this.handleUpdateUser.bind(this), }, { name: "wp_delete_user", description: "Deletes a user.", - parameters: [ - { - name: "id", - type: "number", - required: true, - description: "The ID of the user to delete.", - }, - { - name: "reassign", - type: "number", - description: "The ID of a user to reassign the deleted user's content to.", + inputSchema: { + type: "object", + properties: { + id: { + type: "number", + description: "The ID of the user to delete.", + }, + reassign: { + type: "number", + description: "The ID of a user to reassign the deleted user's content to.", + }, }, - ], + required: ["id"], + }, handler: this.handleDeleteUser.bind(this), }, ]; diff --git a/tests/tool-validation.test.js b/tests/tool-validation.test.js index e36e2c1..e63326f 100644 --- a/tests/tool-validation.test.js +++ b/tests/tool-validation.test.js @@ -45,7 +45,7 @@ describe("Tool Validation", () => { tools.forEach((tool) => { expect(tool).toHaveProperty("name"); expect(tool).toHaveProperty("description"); - expect(tool).toHaveProperty("parameters"); + expect(tool).toHaveProperty("inputSchema"); }); }); @@ -59,7 +59,7 @@ describe("Tool Validation", () => { tools.forEach((tool) => { expect(tool).toHaveProperty("name"); expect(tool).toHaveProperty("description"); - expect(tool).toHaveProperty("parameters"); + expect(tool).toHaveProperty("inputSchema"); }); }); }); diff --git a/tests/tools/auth.test.js b/tests/tools/auth.test.js index 1e6154a..d29ca8a 100644 --- a/tests/tools/auth.test.js +++ b/tests/tools/auth.test.js @@ -40,11 +40,11 @@ describe("AuthTools", () => { tools.forEach((tool) => { expect(tool).toHaveProperty("name"); expect(tool).toHaveProperty("description"); - expect(tool).toHaveProperty("parameters"); + expect(tool).toHaveProperty("inputSchema"); expect(tool).toHaveProperty("handler"); expect(typeof tool.name).toBe("string"); expect(typeof tool.description).toBe("string"); - expect(Array.isArray(tool.parameters)).toBe(true); + expect(typeof tool.inputSchema).toBe("object"); expect(typeof tool.handler).toBe("function"); }); }); @@ -67,24 +67,24 @@ describe("AuthTools", () => { const tools = authTools.getTools(); const switchTool = tools.find((t) => t.name === "wp_switch_auth_method"); - expect(switchTool.parameters).toHaveLength(4); + expect(Object.keys(switchTool.inputSchema.properties)).toHaveLength(4); - const methodParam = switchTool.parameters.find((p) => p.name === "method"); - expect(methodParam).toBeDefined(); - expect(methodParam.required).toBe(true); - expect(methodParam.enum).toEqual(["app-password", "jwt", "basic", "api-key", "cookie"]); + const methodProp = switchTool.inputSchema.properties.method; + expect(methodProp).toBeDefined(); + expect(switchTool.inputSchema.required).toContain("method"); + expect(methodProp.enum).toEqual(["app-password", "jwt", "basic", "api-key", "cookie"]); - const usernameParam = switchTool.parameters.find((p) => p.name === "username"); - expect(usernameParam).toBeDefined(); - expect(usernameParam.required).toBeFalsy(); + const usernameProp = switchTool.inputSchema.properties.username; + expect(usernameProp).toBeDefined(); + expect(switchTool.inputSchema.required).not.toContain("username"); - const passwordParam = switchTool.parameters.find((p) => p.name === "password"); - expect(passwordParam).toBeDefined(); - expect(passwordParam.required).toBeFalsy(); + const passwordProp = switchTool.inputSchema.properties.password; + expect(passwordProp).toBeDefined(); + expect(switchTool.inputSchema.required).not.toContain("password"); - const jwtParam = switchTool.parameters.find((p) => p.name === "jwt_token"); - expect(jwtParam).toBeDefined(); - expect(jwtParam.required).toBeFalsy(); + const jwtProp = switchTool.inputSchema.properties.jwt_token; + expect(jwtProp).toBeDefined(); + expect(switchTool.inputSchema.required).not.toContain("jwt_token"); }); }); @@ -326,13 +326,13 @@ describe("AuthTools", () => { it("should accept all valid authentication methods in tool parameters", () => { const tools = authTools.getTools(); const switchTool = tools.find((t) => t.name === "wp_switch_auth_method"); - const methodParam = switchTool.parameters.find((p) => p.name === "method"); + const methodProp = switchTool.inputSchema.properties.method; const validMethods = ["app-password", "jwt", "basic", "api-key", "cookie"]; - expect(methodParam.enum).toEqual(validMethods); + expect(methodProp.enum).toEqual(validMethods); // Ensure all methods are strings - methodParam.enum.forEach((method) => { + methodProp.enum.forEach((method) => { expect(typeof method).toBe("string"); expect(method.length).toBeGreaterThan(0); }); @@ -342,13 +342,12 @@ describe("AuthTools", () => { const tools = authTools.getTools(); const switchTool = tools.find((t) => t.name === "wp_switch_auth_method"); - switchTool.parameters.forEach((param) => { - expect(param).toHaveProperty("name"); - expect(param).toHaveProperty("type"); - expect(param).toHaveProperty("description"); - expect(typeof param.name).toBe("string"); - expect(typeof param.type).toBe("string"); - expect(typeof param.description).toBe("string"); + Object.entries(switchTool.inputSchema.properties).forEach(([name, prop]) => { + expect(typeof name).toBe("string"); + expect(prop).toHaveProperty("type"); + expect(prop).toHaveProperty("description"); + expect(typeof prop.type).toBe("string"); + expect(typeof prop.description).toBe("string"); }); }); }); diff --git a/tests/tools/comments.test.js b/tests/tools/comments.test.js index cf074d4..8ef6003 100644 --- a/tests/tools/comments.test.js +++ b/tests/tools/comments.test.js @@ -60,43 +60,41 @@ describe("CommentTools", () => { }); // wp_list_comments should have optional post and status parameters - const listParams = toolsByName["wp_list_comments"].parameters; - expect(listParams.find((p) => p.name === "post")).toBeTruthy(); - expect(listParams.find((p) => p.name === "status")).toBeTruthy(); - const statusParam = listParams.find((p) => p.name === "status"); - expect(statusParam.enum).toEqual(["hold", "approve", "spam", "trash"]); + const listProps = toolsByName["wp_list_comments"].inputSchema.properties; + expect(listProps.post).toBeTruthy(); + expect(listProps.status).toBeTruthy(); + expect(listProps.status.enum).toEqual(["hold", "approve", "spam", "trash"]); // wp_get_comment should require id - const getCommentParams = toolsByName["wp_get_comment"].parameters; - const idParam = getCommentParams.find((p) => p.name === "id"); - expect(idParam).toBeTruthy(); - expect(idParam.required).toBe(true); + const getCommentSchema = toolsByName["wp_get_comment"].inputSchema; + expect(getCommentSchema.properties.id).toBeTruthy(); + expect(getCommentSchema.required).toContain("id"); // wp_create_comment should have required post and content parameters - const createParams = toolsByName["wp_create_comment"].parameters; - expect(createParams.find((p) => p.name === "post").required).toBe(true); - expect(createParams.find((p) => p.name === "content").required).toBe(true); - expect(createParams.find((p) => p.name === "author_name")).toBeTruthy(); - expect(createParams.find((p) => p.name === "author_email")).toBeTruthy(); + const createSchema = toolsByName["wp_create_comment"].inputSchema; + expect(createSchema.required).toContain("post"); + expect(createSchema.required).toContain("content"); + expect(createSchema.properties.author_name).toBeTruthy(); + expect(createSchema.properties.author_email).toBeTruthy(); // wp_update_comment should require id - const updateParams = toolsByName["wp_update_comment"].parameters; - expect(updateParams.find((p) => p.name === "id").required).toBe(true); - expect(updateParams.find((p) => p.name === "content")).toBeTruthy(); - expect(updateParams.find((p) => p.name === "status")).toBeTruthy(); + const updateSchema = toolsByName["wp_update_comment"].inputSchema; + expect(updateSchema.required).toContain("id"); + expect(updateSchema.properties.content).toBeTruthy(); + expect(updateSchema.properties.status).toBeTruthy(); // wp_delete_comment should require id - const deleteParams = toolsByName["wp_delete_comment"].parameters; - expect(deleteParams.find((p) => p.name === "id").required).toBe(true); - expect(deleteParams.find((p) => p.name === "force")).toBeTruthy(); + const deleteSchema = toolsByName["wp_delete_comment"].inputSchema; + expect(deleteSchema.required).toContain("id"); + expect(deleteSchema.properties.force).toBeTruthy(); // wp_approve_comment should require id - const approveParams = toolsByName["wp_approve_comment"].parameters; - expect(approveParams.find((p) => p.name === "id").required).toBe(true); + const approveSchema = toolsByName["wp_approve_comment"].inputSchema; + expect(approveSchema.required).toContain("id"); // wp_spam_comment should require id - const spamParams = toolsByName["wp_spam_comment"].parameters; - expect(spamParams.find((p) => p.name === "id").required).toBe(true); + const spamSchema = toolsByName["wp_spam_comment"].inputSchema; + expect(spamSchema.required).toContain("id"); }); }); diff --git a/tests/tools/comments/CommentTools.test.js b/tests/tools/comments/CommentTools.test.js index 91c6a58..8872cda 100644 --- a/tests/tools/comments/CommentTools.test.js +++ b/tests/tools/comments/CommentTools.test.js @@ -67,24 +67,24 @@ describe("CommentTools", () => { const listCommentsTool = tools.find((t) => t.name === "wp_list_comments"); expect(listCommentsTool.description).toContain("Lists comments from a WordPress site"); - expect(listCommentsTool.parameters).toBeDefined(); - expect(Array.isArray(listCommentsTool.parameters)).toBe(true); + expect(listCommentsTool.inputSchema).toBeDefined(); + expect(typeof listCommentsTool.inputSchema).toBe("object"); }); it("should include status enum for comment filters", () => { const tools = commentTools.getTools(); const listCommentsTool = tools.find((t) => t.name === "wp_list_comments"); - const statusParam = listCommentsTool.parameters.find((p) => p.name === "status"); + const statusProp = listCommentsTool.inputSchema.properties.status; - expect(statusParam.enum).toEqual(["hold", "approve", "spam", "trash"]); + expect(statusProp.enum).toEqual(["hold", "approve", "spam", "trash"]); }); it("should include status enum for comment updates", () => { const tools = commentTools.getTools(); const updateCommentTool = tools.find((t) => t.name === "wp_update_comment"); - const statusParam = updateCommentTool.parameters.find((p) => p.name === "status"); + const statusProp = updateCommentTool.inputSchema.properties.status; - expect(statusParam.enum).toEqual(["hold", "approve", "spam", "trash"]); + expect(statusProp.enum).toEqual(["hold", "approve", "spam", "trash"]); }); }); diff --git a/tests/tools/media.test.js b/tests/tools/media.test.js index ed131fe..3425fc7 100644 --- a/tests/tools/media.test.js +++ b/tests/tools/media.test.js @@ -62,39 +62,37 @@ describe("MediaTools", () => { }); // wp_list_media should have optional parameters - expect(toolsByName["wp_list_media"].parameters).toHaveLength(3); - const listParams = toolsByName["wp_list_media"].parameters; - expect(listParams.find((p) => p.name === "per_page")).toBeTruthy(); - expect(listParams.find((p) => p.name === "search")).toBeTruthy(); - expect(listParams.find((p) => p.name === "media_type")).toBeTruthy(); + const listProps = toolsByName["wp_list_media"].inputSchema.properties; + expect(Object.keys(listProps)).toHaveLength(3); + expect(listProps.per_page).toBeTruthy(); + expect(listProps.search).toBeTruthy(); + expect(listProps.media_type).toBeTruthy(); // Check media_type enum values - const mediaTypeParam = listParams.find((p) => p.name === "media_type"); - expect(mediaTypeParam.enum).toEqual(["image", "video", "audio", "application"]); + expect(listProps.media_type.enum).toEqual(["image", "video", "audio", "application"]); // wp_get_media should require id - const getMediaParams = toolsByName["wp_get_media"].parameters; - const idParam = getMediaParams.find((p) => p.name === "id"); - expect(idParam).toBeTruthy(); - expect(idParam.required).toBe(true); + const getMediaSchema = toolsByName["wp_get_media"].inputSchema; + expect(getMediaSchema.properties.id).toBeTruthy(); + expect(getMediaSchema.required).toContain("id"); // wp_upload_media should have file_path as required and other optional params - const uploadParams = toolsByName["wp_upload_media"].parameters; - expect(uploadParams.find((p) => p.name === "file_path")).toBeTruthy(); - expect(uploadParams.find((p) => p.name === "file_path").required).toBe(true); - expect(uploadParams.find((p) => p.name === "title")).toBeTruthy(); - expect(uploadParams.find((p) => p.name === "alt_text")).toBeTruthy(); - expect(uploadParams.find((p) => p.name === "caption")).toBeTruthy(); - expect(uploadParams.find((p) => p.name === "description")).toBeTruthy(); - expect(uploadParams.find((p) => p.name === "post")).toBeTruthy(); + const uploadSchema = toolsByName["wp_upload_media"].inputSchema; + expect(uploadSchema.properties.file_path).toBeTruthy(); + expect(uploadSchema.required).toContain("file_path"); + expect(uploadSchema.properties.title).toBeTruthy(); + expect(uploadSchema.properties.alt_text).toBeTruthy(); + expect(uploadSchema.properties.caption).toBeTruthy(); + expect(uploadSchema.properties.description).toBeTruthy(); + expect(uploadSchema.properties.post).toBeTruthy(); // wp_update_media should require id - const updateParams = toolsByName["wp_update_media"].parameters; - expect(updateParams.find((p) => p.name === "id").required).toBe(true); + const updateSchema = toolsByName["wp_update_media"].inputSchema; + expect(updateSchema.required).toContain("id"); // wp_delete_media should require id - const deleteParams = toolsByName["wp_delete_media"].parameters; - expect(deleteParams.find((p) => p.name === "id").required).toBe(true); + const deleteSchema = toolsByName["wp_delete_media"].inputSchema; + expect(deleteSchema.required).toContain("id"); }); }); diff --git a/tests/tools/media/MediaTools.test.js b/tests/tools/media/MediaTools.test.js index d2b9e4c..cc33f5d 100644 --- a/tests/tools/media/MediaTools.test.js +++ b/tests/tools/media/MediaTools.test.js @@ -88,16 +88,16 @@ describe("MediaTools", () => { const listMediaTool = tools.find((t) => t.name === "wp_list_media"); expect(listMediaTool.description).toContain("Lists media items from a WordPress site"); - expect(listMediaTool.parameters).toBeDefined(); - expect(Array.isArray(listMediaTool.parameters)).toBe(true); + expect(listMediaTool.inputSchema).toBeDefined(); + expect(typeof listMediaTool.inputSchema).toBe("object"); }); it("should include media type enum in list tool", () => { const tools = mediaTools.getTools(); const listMediaTool = tools.find((t) => t.name === "wp_list_media"); - const mediaTypeParam = listMediaTool.parameters.find((p) => p.name === "media_type"); + const mediaTypeProp = listMediaTool.inputSchema.properties.media_type; - expect(mediaTypeParam.enum).toEqual(["image", "video", "audio", "application"]); + expect(mediaTypeProp.enum).toEqual(["image", "video", "audio", "application"]); }); }); diff --git a/tests/tools/pages.test.js b/tests/tools/pages.test.js index 53c1721..ae698b3 100644 --- a/tests/tools/pages.test.js +++ b/tests/tools/pages.test.js @@ -61,31 +61,30 @@ describe("PageTools", () => { }); // wp_list_pages should have optional parameters - expect(toolsByName["wp_list_pages"].parameters).toHaveLength(3); - const listParams = toolsByName["wp_list_pages"].parameters; - expect(listParams.find((p) => p.name === "per_page")).toBeTruthy(); - expect(listParams.find((p) => p.name === "search")).toBeTruthy(); - expect(listParams.find((p) => p.name === "status")).toBeTruthy(); + const listProps = toolsByName["wp_list_pages"].inputSchema.properties; + expect(Object.keys(listProps)).toHaveLength(3); + expect(listProps.per_page).toBeTruthy(); + expect(listProps.search).toBeTruthy(); + expect(listProps.status).toBeTruthy(); // wp_get_page should require id - const getPageParams = toolsByName["wp_get_page"].parameters; - const idParam = getPageParams.find((p) => p.name === "id"); - expect(idParam).toBeTruthy(); - expect(idParam.required).toBe(true); + const getPageSchema = toolsByName["wp_get_page"].inputSchema; + expect(getPageSchema.properties.id).toBeTruthy(); + expect(getPageSchema.required).toContain("id"); // wp_create_page should have title and content parameters - const createParams = toolsByName["wp_create_page"].parameters; - expect(createParams.find((p) => p.name === "title")).toBeTruthy(); - expect(createParams.find((p) => p.name === "content")).toBeTruthy(); - expect(createParams.find((p) => p.name === "title").required).toBe(true); + const createSchema = toolsByName["wp_create_page"].inputSchema; + expect(createSchema.properties.title).toBeTruthy(); + expect(createSchema.properties.content).toBeTruthy(); + expect(createSchema.required).toContain("title"); // wp_update_page should require id - const updateParams = toolsByName["wp_update_page"].parameters; - expect(updateParams.find((p) => p.name === "id").required).toBe(true); + const updateSchema = toolsByName["wp_update_page"].inputSchema; + expect(updateSchema.required).toContain("id"); // wp_delete_page should require id - const deleteParams = toolsByName["wp_delete_page"].parameters; - expect(deleteParams.find((p) => p.name === "id").required).toBe(true); + const deleteSchema = toolsByName["wp_delete_page"].inputSchema; + expect(deleteSchema.required).toContain("id"); }); }); diff --git a/tests/tools/pages/PageTools.test.js b/tests/tools/pages/PageTools.test.js index ded914e..4283c0a 100644 --- a/tests/tools/pages/PageTools.test.js +++ b/tests/tools/pages/PageTools.test.js @@ -65,8 +65,8 @@ describe("PageTools", () => { const listPagesTool = tools.find((t) => t.name === "wp_list_pages"); expect(listPagesTool.description).toContain("Lists pages from a WordPress site"); - expect(listPagesTool.parameters).toBeDefined(); - expect(Array.isArray(listPagesTool.parameters)).toBe(true); + expect(listPagesTool.inputSchema).toBeDefined(); + expect(typeof listPagesTool.inputSchema).toBe("object"); }); }); diff --git a/tests/tools/site.test.js b/tests/tools/site.test.js index 3ecd212..de38ba3 100644 --- a/tests/tools/site.test.js +++ b/tests/tools/site.test.js @@ -42,7 +42,7 @@ describe("SiteTools", () => { tools.forEach((tool) => { expect(tool).toHaveProperty("name"); expect(tool).toHaveProperty("description"); - expect(tool).toHaveProperty("parameters"); + expect(tool).toHaveProperty("inputSchema"); expect(tool).toHaveProperty("handler"); expect(typeof tool.handler).toBe("function"); }); @@ -157,14 +157,14 @@ describe("SiteTools", () => { const tools = siteTools.getTools(); const updateTool = tools.find((t) => t.name === "wp_update_site_settings"); - expect(updateTool.parameters.length).toBeGreaterThan(2); - const titleParam = updateTool.parameters.find((p) => p.name === "title"); - expect(titleParam.type).toBe("string"); + expect(Object.keys(updateTool.inputSchema.properties).length).toBeGreaterThan(2); + const titleProp = updateTool.inputSchema.properties.title; + expect(titleProp.type).toBe("string"); const searchTool = tools.find((t) => t.name === "wp_search_site"); - expect(searchTool.parameters.length).toBeGreaterThan(0); - const termParam = searchTool.parameters.find((p) => p.name === "term"); - expect(termParam.type).toBe("string"); + expect(Object.keys(searchTool.inputSchema.properties).length).toBeGreaterThan(0); + const termProp = searchTool.inputSchema.properties.term; + expect(termProp.type).toBe("string"); }); }); }); diff --git a/tests/tools/taxonomies.test.js b/tests/tools/taxonomies.test.js index 52484d4..17db7d0 100644 --- a/tests/tools/taxonomies.test.js +++ b/tests/tools/taxonomies.test.js @@ -68,38 +68,38 @@ describe("TaxonomyTools", () => { }); // Category tools - const listCatParams = toolsByName["wp_list_categories"].parameters; - expect(listCatParams.find((p) => p.name === "search")).toBeTruthy(); - expect(listCatParams.find((p) => p.name === "hide_empty")).toBeTruthy(); + const listCatProps = toolsByName["wp_list_categories"].inputSchema.properties; + expect(listCatProps.search).toBeTruthy(); + expect(listCatProps.hide_empty).toBeTruthy(); - const getCatParams = toolsByName["wp_get_category"].parameters; - expect(getCatParams.find((p) => p.name === "id").required).toBe(true); + const getCatSchema = toolsByName["wp_get_category"].inputSchema; + expect(getCatSchema.required).toContain("id"); - const createCatParams = toolsByName["wp_create_category"].parameters; - expect(createCatParams.find((p) => p.name === "name").required).toBe(true); - expect(createCatParams.find((p) => p.name === "description")).toBeTruthy(); + const createCatSchema = toolsByName["wp_create_category"].inputSchema; + expect(createCatSchema.required).toContain("name"); + expect(createCatSchema.properties.description).toBeTruthy(); - const updateCatParams = toolsByName["wp_update_category"].parameters; - expect(updateCatParams.find((p) => p.name === "id").required).toBe(true); + const updateCatSchema = toolsByName["wp_update_category"].inputSchema; + expect(updateCatSchema.required).toContain("id"); - const deleteCatParams = toolsByName["wp_delete_category"].parameters; - expect(deleteCatParams.find((p) => p.name === "id").required).toBe(true); + const deleteCatSchema = toolsByName["wp_delete_category"].inputSchema; + expect(deleteCatSchema.required).toContain("id"); // Tag tools - const listTagParams = toolsByName["wp_list_tags"].parameters; - expect(listTagParams.find((p) => p.name === "search")).toBeTruthy(); + const listTagProps = toolsByName["wp_list_tags"].inputSchema.properties; + expect(listTagProps.search).toBeTruthy(); - const getTagParams = toolsByName["wp_get_tag"].parameters; - expect(getTagParams.find((p) => p.name === "id").required).toBe(true); + const getTagSchema = toolsByName["wp_get_tag"].inputSchema; + expect(getTagSchema.required).toContain("id"); - const createTagParams = toolsByName["wp_create_tag"].parameters; - expect(createTagParams.find((p) => p.name === "name").required).toBe(true); + const createTagSchema = toolsByName["wp_create_tag"].inputSchema; + expect(createTagSchema.required).toContain("name"); - const updateTagParams = toolsByName["wp_update_tag"].parameters; - expect(updateTagParams.find((p) => p.name === "id").required).toBe(true); + const updateTagSchema = toolsByName["wp_update_tag"].inputSchema; + expect(updateTagSchema.required).toContain("id"); - const deleteTagParams = toolsByName["wp_delete_tag"].parameters; - expect(deleteTagParams.find((p) => p.name === "id").required).toBe(true); + const deleteTagSchema = toolsByName["wp_delete_tag"].inputSchema; + expect(deleteTagSchema.required).toContain("id"); }); }); diff --git a/tests/tools/taxonomies/TaxonomyTools.test.js b/tests/tools/taxonomies/TaxonomyTools.test.js index e05feb2..f549043 100644 --- a/tests/tools/taxonomies/TaxonomyTools.test.js +++ b/tests/tools/taxonomies/TaxonomyTools.test.js @@ -77,8 +77,8 @@ describe("TaxonomyTools", () => { expect(listCategoriesTool.description).toContain("Lists categories from a WordPress site"); expect(listTagsTool.description).toContain("Lists tags from a WordPress site"); - expect(listCategoriesTool.parameters).toBeDefined(); - expect(listTagsTool.parameters).toBeDefined(); + expect(listCategoriesTool.inputSchema).toBeDefined(); + expect(listTagsTool.inputSchema).toBeDefined(); }); it("should include hide_empty parameter for categories only", () => { @@ -86,12 +86,12 @@ describe("TaxonomyTools", () => { const listCategoriesTool = tools.find((t) => t.name === "wp_list_categories"); const listTagsTool = tools.find((t) => t.name === "wp_list_tags"); - const categoriesHideEmptyParam = listCategoriesTool.parameters.find((p) => p.name === "hide_empty"); - const tagsHideEmptyParam = listTagsTool.parameters.find((p) => p.name === "hide_empty"); + const categoriesHideEmptyProp = listCategoriesTool.inputSchema.properties.hide_empty; + const tagsHideEmptyProp = listTagsTool.inputSchema.properties.hide_empty; - expect(categoriesHideEmptyParam).toBeDefined(); - expect(categoriesHideEmptyParam.type).toBe("boolean"); - expect(tagsHideEmptyParam).toBeUndefined(); + expect(categoriesHideEmptyProp).toBeDefined(); + expect(categoriesHideEmptyProp.type).toBe("boolean"); + expect(tagsHideEmptyProp).toBeUndefined(); }); it("should include description parameter for categories only", () => { @@ -99,11 +99,11 @@ describe("TaxonomyTools", () => { const createCategoryTool = tools.find((t) => t.name === "wp_create_category"); const createTagTool = tools.find((t) => t.name === "wp_create_tag"); - const categoryDescParam = createCategoryTool.parameters.find((p) => p.name === "description"); - const tagDescParam = createTagTool.parameters.find((p) => p.name === "description"); + const categoryDescProp = createCategoryTool.inputSchema.properties.description; + const tagDescProp = createTagTool.inputSchema.properties.description; - expect(categoryDescParam).toBeDefined(); - expect(tagDescParam).toBeUndefined(); + expect(categoryDescProp).toBeDefined(); + expect(tagDescProp).toBeUndefined(); }); }); diff --git a/tests/tools/users.test.js b/tests/tools/users.test.js index c63ae94..aa7e884 100644 --- a/tests/tools/users.test.js +++ b/tests/tools/users.test.js @@ -60,36 +60,35 @@ describe("UserTools", () => { }); // wp_list_users should have optional search and roles parameters - const listParams = toolsByName["wp_list_users"].parameters; - expect(listParams.find((p) => p.name === "search")).toBeTruthy(); - expect(listParams.find((p) => p.name === "roles")).toBeTruthy(); - expect(listParams.find((p) => p.name === "roles").type).toBe("array"); + const listProps = toolsByName["wp_list_users"].inputSchema.properties; + expect(listProps.search).toBeTruthy(); + expect(listProps.roles).toBeTruthy(); + expect(listProps.roles.type).toBe("array"); // wp_get_user should require id - const getUserParams = toolsByName["wp_get_user"].parameters; - const idParam = getUserParams.find((p) => p.name === "id"); - expect(idParam).toBeTruthy(); - expect(idParam.required).toBe(true); + const getUserSchema = toolsByName["wp_get_user"].inputSchema; + expect(getUserSchema.properties.id).toBeTruthy(); + expect(getUserSchema.required).toContain("id"); // wp_get_current_user should have no parameters - const getCurrentUserParams = toolsByName["wp_get_current_user"].parameters; - expect(getCurrentUserParams).toHaveLength(0); + const getCurrentUserProps = toolsByName["wp_get_current_user"].inputSchema.properties; + expect(Object.keys(getCurrentUserProps)).toHaveLength(0); // wp_create_user should have required username, email, password - const createParams = toolsByName["wp_create_user"].parameters; - expect(createParams.find((p) => p.name === "username").required).toBe(true); - expect(createParams.find((p) => p.name === "email").required).toBe(true); - expect(createParams.find((p) => p.name === "password").required).toBe(true); - expect(createParams.find((p) => p.name === "roles")).toBeTruthy(); + const createSchema = toolsByName["wp_create_user"].inputSchema; + expect(createSchema.required).toContain("username"); + expect(createSchema.required).toContain("email"); + expect(createSchema.required).toContain("password"); + expect(createSchema.properties.roles).toBeTruthy(); // wp_update_user should require id - const updateParams = toolsByName["wp_update_user"].parameters; - expect(updateParams.find((p) => p.name === "id").required).toBe(true); + const updateSchema = toolsByName["wp_update_user"].inputSchema; + expect(updateSchema.required).toContain("id"); // wp_delete_user should require id - const deleteParams = toolsByName["wp_delete_user"].parameters; - expect(deleteParams.find((p) => p.name === "id").required).toBe(true); - expect(deleteParams.find((p) => p.name === "reassign")).toBeTruthy(); + const deleteSchema = toolsByName["wp_delete_user"].inputSchema; + expect(deleteSchema.required).toContain("id"); + expect(deleteSchema.properties.reassign).toBeTruthy(); }); }); diff --git a/tests/tools/users/UserTools.test.js b/tests/tools/users/UserTools.test.js index 734f9d5..54f5a25 100644 --- a/tests/tools/users/UserTools.test.js +++ b/tests/tools/users/UserTools.test.js @@ -111,17 +111,17 @@ describe("UserTools", () => { const listUsersTool = tools.find((t) => t.name === "wp_list_users"); expect(listUsersTool.description).toContain("Lists users from a WordPress site"); - expect(listUsersTool.parameters).toBeDefined(); - expect(Array.isArray(listUsersTool.parameters)).toBe(true); + expect(listUsersTool.inputSchema).toBeDefined(); + expect(typeof listUsersTool.inputSchema).toBe("object"); }); it("should include roles parameter for list users", () => { const tools = userTools.getTools(); const listUsersTool = tools.find((t) => t.name === "wp_list_users"); - const rolesParam = listUsersTool.parameters.find((p) => p.name === "roles"); + const rolesProp = listUsersTool.inputSchema.properties.roles; - expect(rolesParam.type).toBe("array"); - expect(rolesParam.items).toEqual({ type: "string" }); + expect(rolesProp.type).toBe("array"); + expect(rolesProp.items).toEqual({ type: "string" }); }); it("should include usage examples in descriptions", () => {