Skip to main content
Glama

wpnav_snapshot_page

Capture complete WordPress page structure including metadata, Gutenberg blocks, featured image, and SEO data for AI analysis and content management.

Instructions

Create a comprehensive snapshot of a WordPress page including metadata, Gutenberg blocks, featured image, and SEO data. Designed for AI agents to understand full page structure.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesWordPress page ID
include_raw_contentNoInclude raw HTML content (default: false)

Implementation Reference

  • Handler function that creates a comprehensive snapshot of a WordPress page, including metadata, Gutenberg blocks, featured image, author info, and SEO data from Yoast or RankMath.
    handler: async (args, context) => { validateRequired(args, ['id']); const id = validateId(args.id, 'Page'); const includeRawContent = args.include_raw_content === true; // Fetch page with all fields const page = await context.wpRequest(`/wp/v2/pages/${id}?context=edit`); // Fetch featured image if set let featuredImage = null; if (page.featured_media && page.featured_media > 0) { try { const media = await context.wpRequest(`/wp/v2/media/${page.featured_media}`); featuredImage = { id: media.id, url: media.source_url, alt: media.alt_text || '', title: media.title?.rendered || '', width: media.media_details?.width, height: media.media_details?.height, }; } catch { featuredImage = { id: page.featured_media, error: 'not_accessible' }; } } // Fetch author info let author = null; if (page.author) { try { const authorData = await context.wpRequest(`/wp/v2/users/${page.author}?_fields=id,name,slug`); author = { id: authorData.id, name: authorData.name, slug: authorData.slug, }; } catch { author = { id: page.author, error: 'not_accessible' }; } } // Parse Gutenberg blocks from raw content const blocks: Array<{ type: string; attrs: Record<string, unknown> }> = []; const rawContent = page.content?.raw || page.content?.rendered || ''; // Simple block parser - extracts block comments from content const blockRegex = /<!-- wp:([a-z0-9-]+\/)?([a-z0-9-]+)(\s+(\{[^}]*\}))?\s*(\/)?-->/g; let match; while ((match = blockRegex.exec(rawContent)) !== null) { const namespace = match[1] ? match[1].slice(0, -1) : 'core'; const blockName = match[2]; const attrsJson = match[4]; let attrs: Record<string, unknown> = {}; if (attrsJson) { try { attrs = JSON.parse(attrsJson); } catch { // Invalid JSON, skip attrs } } blocks.push({ type: `${namespace}/${blockName}`, attrs, }); } // Check for SEO plugins (Yoast or RankMath) let seo = null; if (page.yoast_head_json) { seo = { source: 'yoast', title: page.yoast_head_json.title, description: page.yoast_head_json.description, og_title: page.yoast_head_json.og_title, og_description: page.yoast_head_json.og_description, }; } else if (page.rank_math) { seo = { source: 'rankmath', title: page.rank_math.title, description: page.rank_math.description, }; } // Build snapshot const snapshot: Record<string, unknown> = { id: page.id, metadata: { title: page.title?.rendered || page.title?.raw || '', slug: page.slug, status: page.status, visibility: page.status === 'private' ? 'private' : 'public', template: page.template || '', parent: page.parent || 0, menu_order: page.menu_order || 0, link: page.link, modified: page.modified, modified_gmt: page.modified_gmt, }, author, featured_image: featuredImage, blocks: blocks.length > 0 ? blocks : null, block_count: blocks.length, seo, excerpt: page.excerpt?.rendered || '', }; if (includeRawContent) { snapshot.raw_content = rawContent; } return { content: [{ type: 'text', text: JSON.stringify(snapshot, null, 2) }], }; },
  • Input schema for the wpnav_snapshot_page tool, requiring page ID and optionally including raw content.
    inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'WordPress page ID' }, include_raw_content: { type: 'boolean', description: 'Include raw HTML content (default: false)' }, }, required: ['id'], },
  • Full registration of the wpnav_snapshot_page tool in the tool registry, including definition (name, description, schema) and inline handler.
    // wpnav_snapshot_page - Comprehensive page snapshot for AI agents // ============================================================================ toolRegistry.register({ definition: { name: 'wpnav_snapshot_page', description: 'Create a comprehensive snapshot of a WordPress page including metadata, Gutenberg blocks, featured image, and SEO data. Designed for AI agents to understand full page structure.', inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'WordPress page ID' }, include_raw_content: { type: 'boolean', description: 'Include raw HTML content (default: false)' }, }, required: ['id'], }, }, handler: async (args, context) => { validateRequired(args, ['id']); const id = validateId(args.id, 'Page'); const includeRawContent = args.include_raw_content === true; // Fetch page with all fields const page = await context.wpRequest(`/wp/v2/pages/${id}?context=edit`); // Fetch featured image if set let featuredImage = null; if (page.featured_media && page.featured_media > 0) { try { const media = await context.wpRequest(`/wp/v2/media/${page.featured_media}`); featuredImage = { id: media.id, url: media.source_url, alt: media.alt_text || '', title: media.title?.rendered || '', width: media.media_details?.width, height: media.media_details?.height, }; } catch { featuredImage = { id: page.featured_media, error: 'not_accessible' }; } } // Fetch author info let author = null; if (page.author) { try { const authorData = await context.wpRequest(`/wp/v2/users/${page.author}?_fields=id,name,slug`); author = { id: authorData.id, name: authorData.name, slug: authorData.slug, }; } catch { author = { id: page.author, error: 'not_accessible' }; } } // Parse Gutenberg blocks from raw content const blocks: Array<{ type: string; attrs: Record<string, unknown> }> = []; const rawContent = page.content?.raw || page.content?.rendered || ''; // Simple block parser - extracts block comments from content const blockRegex = /<!-- wp:([a-z0-9-]+\/)?([a-z0-9-]+)(\s+(\{[^}]*\}))?\s*(\/)?-->/g; let match; while ((match = blockRegex.exec(rawContent)) !== null) { const namespace = match[1] ? match[1].slice(0, -1) : 'core'; const blockName = match[2]; const attrsJson = match[4]; let attrs: Record<string, unknown> = {}; if (attrsJson) { try { attrs = JSON.parse(attrsJson); } catch { // Invalid JSON, skip attrs } } blocks.push({ type: `${namespace}/${blockName}`, attrs, }); } // Check for SEO plugins (Yoast or RankMath) let seo = null; if (page.yoast_head_json) { seo = { source: 'yoast', title: page.yoast_head_json.title, description: page.yoast_head_json.description, og_title: page.yoast_head_json.og_title, og_description: page.yoast_head_json.og_description, }; } else if (page.rank_math) { seo = { source: 'rankmath', title: page.rank_math.title, description: page.rank_math.description, }; } // Build snapshot const snapshot: Record<string, unknown> = { id: page.id, metadata: { title: page.title?.rendered || page.title?.raw || '', slug: page.slug, status: page.status, visibility: page.status === 'private' ? 'private' : 'public', template: page.template || '', parent: page.parent || 0, menu_order: page.menu_order || 0, link: page.link, modified: page.modified, modified_gmt: page.modified_gmt, }, author, featured_image: featuredImage, blocks: blocks.length > 0 ? blocks : null, block_count: blocks.length, seo, excerpt: page.excerpt?.rendered || '', }; if (includeRawContent) { snapshot.raw_content = rawContent; } return { content: [{ type: 'text', text: JSON.stringify(snapshot, null, 2) }], }; }, category: ToolCategory.CONTENT, });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/littlebearapps/wp-navigator-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server