refactor: migrate legacy tools to inputSchema format#170
Conversation
Reviewer's GuideRefactors the WordPress MCP tools so that auth, comments, media, pages, site, taxonomies, and users tools expose parameters via a JSON Schema-based Sequence diagram for ToolRegistry resolving legacy parameters vs inputSchemasequenceDiagram
participant ClientCode
participant ToolRegistry
participant PageTools
participant ToolDefinition
ClientCode->>PageTools: getTools()
PageTools-->>ClientCode: Array of ToolDefinition
loop for each tool
ClientCode->>ToolRegistry: buildParameterSchema(tool)
ToolRegistry->>ToolDefinition: check inputSchema
alt tool has inputSchema
ToolDefinition-->>ToolRegistry: inputSchema
ToolRegistry-->>ClientCode: MCPToolSchema from inputSchema
else tool has legacy parameters
ToolDefinition-->>ToolRegistry: parameters array
ToolRegistry-->>ClientCode: MCPToolSchema converted from parameters
end
end
Class diagram for WordPress tools using inputSchemaclassDiagram
class WordPressClient
class MCPToolSchema {
+string type
+object properties
+string[] required
}
class ToolDefinition {
+string name
+string description
+MCPToolSchema inputSchema
+handler(client WordPressClient, params Record)
}
class AuthTools {
+getTools() Array~ToolDefinition~
-handleTestAuth(client WordPressClient, params Record)
-handleGetAuthStatus(client WordPressClient, params Record)
-handleSwitchAuthMethod(client WordPressClient, params Record)
}
class CommentTools {
+getTools() Array~ToolDefinition~
-handleListComments(client WordPressClient, params Record)
-handleGetComment(client WordPressClient, params Record)
-handleCreateComment(client WordPressClient, params Record)
-handleUpdateComment(client WordPressClient, params Record)
-handleDeleteComment(client WordPressClient, params Record)
-handleApproveComment(client WordPressClient, params Record)
-handleSpamComment(client WordPressClient, params Record)
}
class MediaTools {
+getTools() Array~ToolDefinition~
-handleListMedia(client WordPressClient, params Record)
-handleGetMedia(client WordPressClient, params Record)
-handleUploadMedia(client WordPressClient, params Record)
-handleUpdateMedia(client WordPressClient, params Record)
-handleDeleteMedia(client WordPressClient, params Record)
}
class PageTools {
+getTools() Array~ToolDefinition~
-handleListPages(client WordPressClient, params Record)
-handleGetPage(client WordPressClient, params Record)
-handleCreatePage(client WordPressClient, params Record)
-handleUpdatePage(client WordPressClient, params Record)
-handleDeletePage(client WordPressClient, params Record)
-handleGetPageRevisions(client WordPressClient, params Record)
}
class SiteTools {
+getTools() Array~ToolDefinition~
-handleGetSiteSettings(client WordPressClient, params Record)
-handleUpdateSiteSettings(client WordPressClient, params Record)
-handleSearchSite(client WordPressClient, params Record)
-handleGetApplicationPasswords(client WordPressClient, params Record)
-handleCreateApplicationPassword(client WordPressClient, params Record)
-handleDeleteApplicationPassword(client WordPressClient, params Record)
}
class TaxonomyTools {
+getTools() Array~ToolDefinition~
-handleListCategories(client WordPressClient, params Record)
-handleGetCategory(client WordPressClient, params Record)
-handleCreateCategory(client WordPressClient, params Record)
-handleUpdateCategory(client WordPressClient, params Record)
-handleDeleteCategory(client WordPressClient, params Record)
-handleListTags(client WordPressClient, params Record)
-handleGetTag(client WordPressClient, params Record)
-handleCreateTag(client WordPressClient, params Record)
-handleUpdateTag(client WordPressClient, params Record)
-handleDeleteTag(client WordPressClient, params Record)
}
class UserTools {
+getTools() Array~ToolDefinition~
-handleListUsers(client WordPressClient, params Record)
-handleGetUser(client WordPressClient, params Record)
-handleGetCurrentUser(client WordPressClient, params Record)
-handleCreateUser(client WordPressClient, params Record)
-handleUpdateUser(client WordPressClient, params Record)
-handleDeleteUser(client WordPressClient, params Record)
}
class ToolRegistry {
+buildParameterSchema(tool ToolDefinition) MCPToolSchema
}
AuthTools --> ToolDefinition
CommentTools --> ToolDefinition
MediaTools --> ToolDefinition
PageTools --> ToolDefinition
SiteTools --> ToolDefinition
TaxonomyTools --> ToolDefinition
UserTools --> ToolDefinition
ToolDefinition --> MCPToolSchema
ToolDefinition --> WordPressClient : handler uses
ToolRegistry --> ToolDefinition : consumes
ToolRegistry --> MCPToolSchema : returns
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- There’s a lot of repeated inline JSON Schema for common patterns (e.g. simple
id-required objects, list-with-search filters, etc.); consider extracting small helpers/factories for these to reduce duplication and keep future schema changes consistent across tools. - For tools that are intended to have no arguments (e.g.
wp_get_site_settings,wp_get_current_user, auth status tools), you may want to addadditionalProperties: falseto theirinputSchemato prevent accidental extra parameters and better reflect the contract.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There’s a lot of repeated inline JSON Schema for common patterns (e.g. simple `id`-required objects, list-with-search filters, etc.); consider extracting small helpers/factories for these to reduce duplication and keep future schema changes consistent across tools.
- For tools that are intended to have no arguments (e.g. `wp_get_site_settings`, `wp_get_current_user`, auth status tools), you may want to add `additionalProperties: false` to their `inputSchema` to prevent accidental extra parameters and better reflect the contract.
## Individual Comments
### Comment 1
<location path="src/tools/auth.ts" line_range="32-35" />
<code_context>
"• 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),
</code_context>
<issue_to_address>
**question (bug_risk):** Consider aligning the `wp_test_auth` schema with how the dynamic `site` parameter is injected and validated.
With `inputSchema` now defined as an empty object, any dynamically injected `site` field may not be represented in the runtime schema. Please confirm that either (a) the effective schema at validation time includes `site`, or (b) this tool’s validation is configured to allow unknown properties, so callers don’t hit schema/validation mismatches compared to tools where all fields are declared.
</issue_to_address>
### Comment 2
<location path="tests/tools/auth.test.js" line_range="72-81" />
<code_context>
+ const methodProp = switchTool.inputSchema.properties.method;
</code_context>
<issue_to_address>
**suggestion (testing):** Add an explicit check for tools that should have no user-supplied parameters (empty `properties`)
Since `wp_test_connection` and `wp_get_auth_status` now use an empty `inputSchema` with parameters added server-side, add an assertion in the auth tests that `Object.keys(tool.inputSchema.properties).length === 0` for these tools. This will guard against accidentally introducing user-facing parameters while still passing the tests.
</issue_to_address>
### Comment 3
<location path="tests/tool-validation.test.js" line_range="48" />
<code_context>
expect(tool).toHaveProperty("name");
expect(tool).toHaveProperty("description");
- expect(tool).toHaveProperty("parameters");
+ expect(tool).toHaveProperty("inputSchema");
});
});
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen global tool validation to verify `inputSchema` structure, not just presence
Since this is the central invariant check for all tools, it’s a good place to validate the basic JSON Schema shape of `inputSchema`, not just its presence. For example, assert that `inputSchema.type === "object"`, `inputSchema.properties` is an object, and if `required` is present, it’s an array. That will better protect the migration from regressions without duplicating checks in individual tool tests.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| // The 'site' parameter is added dynamically by the server | ||
| inputSchema: { | ||
| type: "object", | ||
| properties: {}, |
There was a problem hiding this comment.
question (bug_risk): Consider aligning the wp_test_auth schema with how the dynamic site parameter is injected and validated.
With inputSchema now defined as an empty object, any dynamically injected site field may not be represented in the runtime schema. Please confirm that either (a) the effective schema at validation time includes site, or (b) this tool’s validation is configured to allow unknown properties, so callers don’t hit schema/validation mismatches compared to tools where all fields are declared.
| 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; |
There was a problem hiding this comment.
suggestion (testing): Add an explicit check for tools that should have no user-supplied parameters (empty properties)
Since wp_test_connection and wp_get_auth_status now use an empty inputSchema with parameters added server-side, add an assertion in the auth tests that Object.keys(tool.inputSchema.properties).length === 0 for these tools. This will guard against accidentally introducing user-facing parameters while still passing the tests.
| expect(tool).toHaveProperty("name"); | ||
| expect(tool).toHaveProperty("description"); | ||
| expect(tool).toHaveProperty("parameters"); | ||
| expect(tool).toHaveProperty("inputSchema"); |
There was a problem hiding this comment.
suggestion (testing): Strengthen global tool validation to verify inputSchema structure, not just presence
Since this is the central invariant check for all tools, it’s a good place to validate the basic JSON Schema shape of inputSchema, not just its presence. For example, assert that inputSchema.type === "object", inputSchema.properties is an object, and if required is present, it’s an array. That will better protect the migration from regressions without duplicating checks in individual tool tests.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c0fae7082f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| enum?: string[]; | ||
| items?: unknown; | ||
| }>; | ||
| inputSchema?: MCPToolSchema; |
There was a problem hiding this comment.
Handle inputSchema tools in documentation generator
After this migration, these tool classes no longer expose parameters, but the docs pipeline still reads only toolDef.parameters (for parameter extraction and example generation in src/docs/DocumentationGenerator.ts). As a result, running docs/OpenAPI generation now produces incomplete docs for migrated tools (missing parameter tables, required args, and realistic examples) even though the tools do accept those inputs via inputSchema.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR migrates legacy WordPress tool modules from the old parameters[] format to MCP’s standard inputSchema JSON Schema format, aligning them with the existing posts/SEO tooling patterns and updating tests accordingly.
Changes:
- Refactor 7 tool modules (auth, comments, media, pages, site, taxonomies, users) to define parameters via
inputSchemainstead ofparameters. - Update tool-focused test suites to assert against
inputSchema.properties/inputSchema.required. - Maintain ToolRegistry backward compatibility by still supporting both formats during schema building.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tools/auth.ts | Converts auth tools to inputSchema definitions. |
| src/tools/comments.ts | Converts comment tools to inputSchema definitions. |
| src/tools/media.ts | Converts media tools to inputSchema definitions. |
| src/tools/pages.ts | Converts page tools to inputSchema definitions. |
| src/tools/site.ts | Converts site tools to inputSchema definitions. |
| src/tools/taxonomies.ts | Converts taxonomy tools to inputSchema definitions. |
| src/tools/users.ts | Converts user tools to inputSchema definitions. |
| tests/tools/auth.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/comments.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/comments/CommentTools.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/media.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/media/MediaTools.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/pages.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/pages/PageTools.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/site.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/taxonomies.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/taxonomies/TaxonomyTools.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/users.test.js | Updates assertions from parameters to inputSchema. |
| tests/tools/users/UserTools.test.js | Updates assertions from parameters to inputSchema. |
| tests/tool-validation.test.js | Updates tool shape validation to require inputSchema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| */ | ||
| 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<string, unknown>) => Promise<unknown>; | ||
| }> { |
| @@ -1,4 +1,5 @@ | |||
| import { WordPressClient } from "@/client/api.js"; | |||
| import { MCPToolSchema } from "@/types/mcp.js"; | |||
| enum: ["publish", "future", "draft", "pending", "private"], | ||
| }, | ||
| ], | ||
| required: [], |
Convert 7 tool modules (auth, comments, media, pages, site, taxonomies, users) from the legacy parameters array format to the standard inputSchema JSON Schema format, matching the pattern already used by posts and SEO tools. - Replace parameters arrays with inputSchema objects - Use JSON Schema properties, required, and enum fields - Update 13 test files to assert on inputSchema instead of parameters Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
c0fae70 to
fbca260
Compare
## [3.1.12](v3.1.11...v3.1.12) (2026-03-15) ### ♻️ Refactoring * migrate legacy tools to inputSchema JSON Schema format ([#170](#170)) ([067aa3e](067aa3e))
|
🎉 This PR is included in version 3.1.12 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
parametersarray format to standardinputSchemaJSON Schema formatinputSchemainstead ofparametersDetails
The MCP SDK uses JSON Schema (
inputSchema) for tool parameter definitions. The posts and SEO tools already used this format, but the remaining 7 tool modules still used a legacyparametersarray format that required conversion inToolRegistry.buildParameterSchema(). This PR eliminates that inconsistency.The
ToolRegistrystill supports both formats for backward compatibility (cache and performance tools remain on the old format for now).Test plan
🤖 Generated with Claude Code
Summary by Sourcery
Migrate remaining WordPress tool modules from the legacy parameters array to the unified inputSchema JSON Schema format and update tests accordingly.
Enhancements:
Tests: