import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { WordPressClient } from "../client/api.js"; import type { MCPToolSchema } from "../types/mcp.js"; /** * Interface for tool definition */ export interface ToolDefinition { name: string; description?: string; parameters?: Array<{ name: string; type?: string; description?: string; required?: boolean; enum?: string[]; items?: { type?: string; }; }>; inputSchema?: MCPToolSchema; handler: (client: WordPressClient, args: Record) => Promise; } /** * Registry for managing MCP tools * Handles tool registration, parameter validation, and execution */ export declare class ToolRegistry { server: McpServer; wordpressClients: Map; private _cachedToolsListResponse; constructor(server: McpServer, wordpressClients: Map); /** * Register all available tools with the MCP server */ registerAllTools(): void; /** * Build and install a cached tools/list handler, bypassing the SDK's per-request * Zod→JSON-Schema conversion for all 71 tools. */ private installCachedToolsListHandler; /** * Register a single tool with parameter validation and execution handling */ private registerTool; /** * Build a plain JSON Schema object for a tool's input, including the `site` parameter. * Used to pre-build the tools/list response so the SDK's per-request Zod conversion * is replaced by a single pre-computed snapshot. */ private buildCachedInputSchema; /** * Build Zod parameter schema from tool definition */ private buildParameterSchema; /** * Get appropriate Zod type for inputSchema property definition. `propName` (when known) picks * the right security boundary for string properties — see WORDPRESS_CONTENT_PARAM_NAMES. */ private getZodTypeForProperty; /** * Get appropriate Zod type for parameter definition (old format) */ private getZodTypeForParameter; /** * Return the single configured site ID. * Only called after the multi-site guard (which requires an explicit `site` param), * so this path is only reached in single-site mode. */ private selectBestSite; /** * Check if error is authentication-related. * * Checks `statusCode` on the real `WordPressAPIError` hierarchy (`src/types/client.ts`), * not `error.response.status`/`error.code === "WORDPRESS_AUTH_ERROR"` — those never match * anything the client pipeline actually throws (it sets `statusCode` directly on the error, * with no `.response` wrapper, and uses `"authentication_failed"` as the code). Checking * `statusCode` rather than `instanceof AuthenticationError` also catches a bare 401 on a * non-media endpoint, which the client throws as a plain `WordPressAPIError`, not the * `AuthenticationError` subclass (that subtype is only used for media-upload 401/403). * * A bare 403 from WordPress is treated as a permission denial (auth-related). But a 403 * carrying an explicit error code is NOT: `validateFilePath` * (src/utils/validation/security.ts) throws 403s like `UPLOADS_DISABLED`, * `PATH_TRAVERSAL_ATTEMPT`, `SYMLINK_NOT_ALLOWED`, `NOT_A_REGULAR_FILE` that are local * configuration/validation failures, not authentication problems. Classifying them as * authentication errors here made `wp_upload_media` report "Authentication failed for site * 'default'" when the real cause was that MCP_UPLOAD_BASE_DIR was not set — hiding the * actual fix behind a misleading credentials error. */ private isAuthenticationError; } //# sourceMappingURL=ToolRegistry.d.ts.map