wp_seo_generate_metadata
Generate SEO-optimized metadata for WordPress posts including title tags, meta descriptions, OpenGraph, and Twitter Card data to improve search visibility.
Instructions
Generate SEO-optimized metadata including title tags, meta descriptions, OpenGraph, and Twitter Card data
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | Site identifier for multi-site setups | |
| postId | Yes | WordPress post ID | |
| title | No | Custom title to optimize (optional, uses post title if not provided) | |
| description | No | Custom description to optimize (optional, uses excerpt if not provided) | |
| focusKeyword | No | Primary keyword to include in metadata |
Implementation Reference
- src/tools/seo/SEOHandlers.ts:54-80 (handler)MCP handler function that executes the wp_seo_generate_metadata tool logic by extracting parameters from args and delegating to SEOTools.generateMetadataexport async function handleGenerateMetadata(client: WordPressClient, args: Record<string, unknown>): Promise<unknown> { const logger = LoggerFactory.tool("wp_seo_generate_metadata"); try { const seoTools = getSEOToolsInstance(); const params: SEOToolParams = { postId: args.postId as number, site: args.site as string, }; // Add custom title/description if provided if (args.title) { params.title = args.title as string; } if (args.description) { params.description = args.description as string; } if (args.focusKeyword) { params.focusKeywords = [args.focusKeyword as string]; } return await seoTools.generateMetadata(params); } catch (error) { logger.error("Failed to generate metadata", { error, args }); throw error; } }
- Input schema and definition for the wp_seo_generate_metadata toolexport const generateMetadataTool: Tool = { name: "wp_seo_generate_metadata", description: "Generate SEO-optimized metadata including title tags, meta descriptions, OpenGraph, and Twitter Card data", inputSchema: { type: "object", properties: { postId: { type: "number", description: "WordPress post ID", }, title: { type: "string", description: "Custom title to optimize (optional, uses post title if not provided)", }, description: { type: "string", description: "Custom description to optimize (optional, uses excerpt if not provided)", }, focusKeyword: { type: "string", description: "Primary keyword to include in metadata", }, site: { type: "string", description: "Site identifier for multi-site setups", }, }, required: ["postId"], }, };
- src/tools/seo/SEOTools.ts:378-399 (registration)Registration mapping in getHandlerForTool that associates 'wp_seo_generate_metadata' with handleGenerateMetadata handler. Used by getTools() for MCP tool registration.private getHandlerForTool(toolName: string): unknown { const handlers: Record<string, unknown> = { wp_seo_analyze_content: handleAnalyzeContent, wp_seo_generate_metadata: handleGenerateMetadata, wp_seo_bulk_update_metadata: handleBulkUpdateMetadata, wp_seo_generate_schema: handleGenerateSchema, wp_seo_validate_schema: handleValidateSchema, wp_seo_suggest_internal_links: handleSuggestInternalLinks, wp_seo_site_audit: handlePerformSiteAudit, wp_seo_track_serp: handleTrackSERPPositions, wp_seo_keyword_research: handleKeywordResearch, wp_seo_test_integration: handleTestSEOIntegration, wp_seo_get_live_data: handleGetLiveSEOData, }; return ( handlers[toolName] || (() => { throw new Error(`Unknown SEO tool: ${toolName}`); }) ); }
- src/tools/seo/SEOTools.ts:150-170 (helper)Core generateMetadata method in SEOTools class that orchestrates metadata generation by calling createMetadata (which uses MetaGenerator).async generateMetadata(params: SEOToolParams): Promise<SEOMetadata> { const siteLogger = LoggerFactory.tool("wp_seo_generate_meta", params.site); return await siteLogger.time("Generate SEO metadata", async () => { try { validateRequired(params, ["postId"]); const client = this.getSiteClient(params.site); // Implementation will be added in generators const metadata = await this.createMetadata(client, params); return metadata; } catch (_error) { handleToolError(_error, "generate metadata", { site: params.site, postId: params.postId as number, }); throw _error; } }); }
- The core implementation logic in MetaGenerator.generateMetadata that generates title, description, OpenGraph, Twitter Card, applies safety filters, and validates the SEO metadata.async generateMetadata( post: WordPressPost, params: SEOToolParams, options: MetaGenerationOptions = {}, ): Promise<SEOMetadata> { const siteLogger = LoggerFactory.tool("seo_generate_metadata", params.site); return await siteLogger.time("Generate SEO metadata", async () => { // Extract content for analysis const content = this.extractPostContent(post); const focusKeyword = params.focusKeywords?.[0] || ""; // Generate title tag const title = await this.generateTitle(post, content, focusKeyword, options); // Generate meta description const description = await this.generateDescription(post, content, focusKeyword, options); // Generate OpenGraph metadata const openGraph = await this.generateOpenGraph(post, title, description, options); // Generate Twitter Card metadata const twitterCard = await this.generateTwitterCard(post, title, description, options); // Create canonical URL const canonical = this.generateCanonicalUrl(post); // Set robots directives const robots = this.generateRobotsDirectives(post, options); const metadata: SEOMetadata = { title, description, }; if (focusKeyword) { metadata.focusKeyword = focusKeyword; } if (canonical) { metadata.canonical = canonical; } if (robots) { metadata.robots = robots; } if (openGraph) { metadata.openGraph = openGraph; } if (twitterCard) { metadata.twitterCard = twitterCard; } // Apply safety filters this.applySafetyFilters(metadata); // Re-optimize description length after safety filters may have shortened it metadata.description = this.optimizeDescriptionLength(metadata.description); // Validate required fields this.validateMetadata(metadata); siteLogger.info("Generated SEO metadata", { titleLength: title.length, descriptionLength: description.length, hasOpenGraph: Boolean(openGraph), hasTwitterCard: Boolean(twitterCard), focusKeyword, }); return metadata; }); }