Skip to main content
Glama

wpnav_update_post

Update WordPress posts by modifying title, content, excerpt, or status while maintaining an audit trail for tracking changes.

Instructions

Update a WordPress post. Requires post ID and at least one field to update. Changes are logged in audit trail.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesWordPress post ID
titleNoNew post title
contentNoNew post content (HTML).
excerptNoPost excerpt
statusNoPost status: publish, draft, private
forceNoSkip safety validation

Implementation Reference

  • The handler function implementing the wpnav_update_post tool logic: validates args, builds JSON Patch operations for title/content/excerpt/status, calls applyContentChanges safety wrapper, returns result or formatted error.
    handler: async (args, context) => { try { validateRequired(args, ['id']); const id = validateId(args.id, 'Post'); const ops: any[] = []; if (args.title != null) ops.push({ op: 'replace', path: '/title', value: String(args.title) }); if (args.content != null) ops.push({ op: 'replace', path: '/content', value: String(args.content) }); if (args.excerpt != null) ops.push({ op: 'replace', path: '/excerpt', value: String(args.excerpt) }); if (args.status != null) ops.push({ op: 'replace', path: '/status', value: String(args.status) }); if (!ops.length) { return { content: [{ type: 'text', text: JSON.stringify({ error: 'validation_failed', code: 'VALIDATION_FAILED', message: 'At least one of title, content, excerpt, or status must be provided', context: { resource_type: 'post', resource_id: id }, }, null, 2), }], isError: true, }; } const result = await applyContentChanges(context.wpRequest as any, context.config, { postId: id, operations: ops, force: !!args.force, }); return { content: [{ type: 'text', text: context.clampText(JSON.stringify(result, null, 2)) }], }; } catch (error: any) { const errorMessage = error.message || 'Unknown error'; const isWritesDisabled = errorMessage.includes('WRITES_DISABLED'); return { content: [{ type: 'text', text: JSON.stringify({ error: isWritesDisabled ? 'writes_disabled' : 'operation_failed', code: isWritesDisabled ? 'WRITES_DISABLED' : 'UPDATE_FAILED', message: errorMessage, context: { resource_type: 'post', resource_id: args.id, suggestion: 'Use wpnav_get_post to verify post exists' }, }, null, 2), }], isError: true, }; } },
  • JSON Schema defining input parameters and validation for wpnav_update_post tool.
    inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'WordPress post ID' }, title: { type: 'string', description: 'New post title' }, content: { type: 'string', description: 'New post content (HTML).' }, excerpt: { type: 'string', description: 'Post excerpt' }, status: { type: 'string', enum: ['publish', 'draft', 'private'], description: 'Post status: publish, draft, private' }, force: { type: 'boolean', description: 'Skip safety validation', default: false }, }, required: ['id'], },
  • Registration of the wpnav_update_post tool with toolRegistry, including definition, handler, and category.
    toolRegistry.register({ definition: { name: 'wpnav_update_post', description: 'Update a WordPress post. Requires post ID and at least one field to update. Changes are logged in audit trail.', inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'WordPress post ID' }, title: { type: 'string', description: 'New post title' }, content: { type: 'string', description: 'New post content (HTML).' }, excerpt: { type: 'string', description: 'Post excerpt' }, status: { type: 'string', enum: ['publish', 'draft', 'private'], description: 'Post status: publish, draft, private' }, force: { type: 'boolean', description: 'Skip safety validation', default: false }, }, required: ['id'], }, }, handler: async (args, context) => { try { validateRequired(args, ['id']); const id = validateId(args.id, 'Post'); const ops: any[] = []; if (args.title != null) ops.push({ op: 'replace', path: '/title', value: String(args.title) }); if (args.content != null) ops.push({ op: 'replace', path: '/content', value: String(args.content) }); if (args.excerpt != null) ops.push({ op: 'replace', path: '/excerpt', value: String(args.excerpt) }); if (args.status != null) ops.push({ op: 'replace', path: '/status', value: String(args.status) }); if (!ops.length) { return { content: [{ type: 'text', text: JSON.stringify({ error: 'validation_failed', code: 'VALIDATION_FAILED', message: 'At least one of title, content, excerpt, or status must be provided', context: { resource_type: 'post', resource_id: id }, }, null, 2), }], isError: true, }; } const result = await applyContentChanges(context.wpRequest as any, context.config, { postId: id, operations: ops, force: !!args.force, }); return { content: [{ type: 'text', text: context.clampText(JSON.stringify(result, null, 2)) }], }; } catch (error: any) { const errorMessage = error.message || 'Unknown error'; const isWritesDisabled = errorMessage.includes('WRITES_DISABLED'); return { content: [{ type: 'text', text: JSON.stringify({ error: isWritesDisabled ? 'writes_disabled' : 'operation_failed', code: isWritesDisabled ? 'WRITES_DISABLED' : 'UPDATE_FAILED', message: errorMessage, context: { resource_type: 'post', resource_id: args.id, suggestion: 'Use wpnav_get_post to verify post exists' }, }, null, 2), }], isError: true, }; } }, category: ToolCategory.CONTENT, });
  • Core helper function applyContentChanges that performs the safe plan/diff/apply workflow via WP Navigator endpoints for content updates, called by the tool handler.
    export async function applyContentChanges( wpRequest: WpRequest, config: WPConfig, opts: ApplyContentOptions ) { const idempotencyKey = makeIdempotencyKey(); // 1) Plan const plan = await wpRequest('/wpnav/v1/content/plan', { method: 'POST', body: JSON.stringify({ post_id: opts.postId, operations: opts.operations, idempotency_key: idempotencyKey, }), }); const planId = plan?.plan_id ?? plan?.id ?? plan?.planId; if (!planId) { throw new Error(`PLAN_FAILED: Could not retrieve plan_id from response`); } // 2) Diff (json format; small context) const diff = await wpRequest('/wpnav/v1/content/diff', { method: 'POST', body: JSON.stringify({ plan_id: planId, format: 'json', context_lines: 3, }), }); // 3) Apply const apply = await wpRequest('/wpnav/v1/content/apply', { method: 'POST', body: JSON.stringify({ plan_id: planId, idempotency_key: idempotencyKey, force: !!opts.force, }), }); return { plan, diff, apply }; }

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