Skip to main content
Glama

wp_update_post

Update existing WordPress posts by modifying title, content, status, categories, tags, featured media, or publication date with comprehensive validation and change tracking.

Instructions

Updates an existing WordPress post with comprehensive validation and change tracking. All parameters except ID are optional - only provided fields will be updated.

Usage Examples: • Update title: wp_update_post --id=123 --title="New Title" • Update content: wp_update_post --id=123 --content="<p>Updated content</p>" • Change status: wp_update_post --id=123 --status="publish" • Update categories: wp_update_post --id=123 --categories=[1,5,10] • Set featured image: wp_update_post --id=123 --featured_media=42 • Remove featured image: wp_update_post --id=123 --featured_media=0 • Multiple updates: wp_update_post --id=123 --title="New Title" --status="publish" --categories=[1,2]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
siteNoThe ID of the WordPress site to target (from mcp-wordpress.config.json). Required if multiple sites are configured.
idYesThe ID of the post to update.
titleNoThe new title for the post.
contentNoThe new content for the post, in HTML format.
statusNoThe new publishing status for the post.
excerptNoThe new excerpt for the post.
categoriesNoAn array of category IDs to assign to the post.
tagsNoAn array of tag IDs to assign to the post.
featured_mediaNoThe ID of the featured media (image). Use 0 to remove featured media.
dateNoThe date the post was published, in the site's timezone (ISO 8601 format).

Implementation Reference

  • Core handler function that executes the wp_update_post tool: validates parameters, fetches original post for change detection, performs the update via WordPressClient, generates a summary of changes, and returns formatted response.
    export async function handleUpdatePost(
      client: WordPressClient,
      params: UpdatePostRequest & { id: number },
    ): Promise<WordPressPost | string> {
      try {
        const postId = validateId(params.id, "post ID");
    
        // Get original post to show what changed
        const originalPost = await client.getPost(postId);
    
        const { id: _id, ...updateData } = params;
        validatePostParams(updateData);
    
        const updatedPost = await client.updatePost({ id: postId, ...updateData });
    
        // Build change summary
        let response = `✅ **Post Updated Successfully**\n\n`;
        response += `**Title**: ${updatedPost.title.rendered}\n`;
        response += `**ID**: ${updatedPost.id}\n`;
        response += `**Status**: ${updatedPost.status}\n`;
        response += `**Modified**: ${new Date(updatedPost.modified).toLocaleString()}\n`;
    
        // Show what changed
        const changes: string[] = [];
        if (params.title && originalPost.title.rendered !== updatedPost.title.rendered) {
          changes.push(`Title: "${originalPost.title.rendered}" → "${updatedPost.title.rendered}"`);
        }
        if (params.status && originalPost.status !== updatedPost.status) {
          changes.push(`Status: "${originalPost.status}" → "${updatedPost.status}"`);
        }
        if (params.content && originalPost.content?.rendered !== updatedPost.content?.rendered) {
          changes.push("Content updated");
        }
        if (params.excerpt && originalPost.excerpt?.rendered !== updatedPost.excerpt?.rendered) {
          changes.push("Excerpt updated");
        }
    
        if (changes.length > 0) {
          response += `\n**Changes Made**:\n${changes.map((c) => `- ${c}`).join("\n")}\n`;
        }
    
        response += `\n**Link**: ${updatedPost.link}`;
    
        return response;
      } catch (_error) {
        if (_error instanceof Error && _error.message.includes("404")) {
          return `Post with ID ${params.id} not found. Please verify the ID and try again.`;
        }
        throw new Error(`Failed to update post: ${getErrorMessage(_error)}`);
      }
    }
  • Input schema definition for the wp_update_post tool, including all parameters, descriptions, types, and required fields.
    export const updatePostTool: MCPTool = {
      name: "wp_update_post",
      description:
        "Updates an existing WordPress post with comprehensive validation and change tracking. All parameters except ID are optional - only provided fields will be updated.\n\n" +
        "**Usage Examples:**\n" +
        '• Update title: `wp_update_post --id=123 --title="New Title"`\n' +
        '• Update content: `wp_update_post --id=123 --content="<p>Updated content</p>"`\n' +
        '• Change status: `wp_update_post --id=123 --status="publish"`\n' +
        "• Update categories: `wp_update_post --id=123 --categories=[1,5,10]`\n" +
        "• Set featured image: `wp_update_post --id=123 --featured_media=42`\n" +
        "• Remove featured image: `wp_update_post --id=123 --featured_media=0`\n" +
        '• Multiple updates: `wp_update_post --id=123 --title="New Title" --status="publish" --categories=[1,2]`',
      inputSchema: {
        type: "object",
        properties: {
          id: {
            type: "number",
            description: "The ID of the post to update.",
          },
          title: {
            type: "string",
            description: "The new title for the post.",
          },
          content: {
            type: "string",
            description: "The new content for the post, in HTML format.",
          },
          status: {
            type: "string",
            description: "The new publishing status for the post.",
            enum: ["publish", "draft", "pending", "private"],
          },
          excerpt: {
            type: "string",
            description: "The new excerpt for the post.",
          },
          categories: {
            type: "array",
            items: { type: "number" },
            description: "An array of category IDs to assign to the post.",
          },
          tags: {
            type: "array",
            items: { type: "number" },
            description: "An array of tag IDs to assign to the post.",
          },
          featured_media: {
            type: "number",
            description: "The ID of the featured media (image). Use 0 to remove featured media.",
          },
          date: {
            type: "string",
            description: "The date the post was published, in the site's timezone (ISO 8601 format).",
          },
        },
        required: ["id"],
      },
    };
  • Switch statement in PostTools.getHandlerForTool that binds the handleUpdatePost method as the handler for 'wp_update_post' tool.
    private getHandlerForTool(toolName: string) {
      switch (toolName) {
        case "wp_list_posts":
          return this.handleListPosts.bind(this);
        case "wp_get_post":
          return this.handleGetPost.bind(this);
        case "wp_create_post":
          return this.handleCreatePost.bind(this);
        case "wp_update_post":
          return this.handleUpdatePost.bind(this);
        case "wp_delete_post":
          return this.handleDeletePost.bind(this);
        case "wp_get_post_revisions":
          return this.handleGetPostRevisions.bind(this);
        default:
          throw new Error(`Unknown tool: ${toolName}`);
      }
    }
  • PostTools.getTools() method that combines tool definitions with their bound handlers, making the tools ready for MCP server registration.
    public getTools(): unknown[] {
      return postToolDefinitions.map((toolDef) => ({
        ...toolDef,
        handler: this.getHandlerForTool(toolDef.name),
      }));
  • ToolRegistry.registerAllTools() instantiates PostTools (via Tools import) and registers all its tools including wp_update_post with the MCP server.
    public registerAllTools(): void {
      // Register all tools from the tools directory
      Object.values(Tools).forEach((ToolClass) => {
        let toolInstance: { getTools(): unknown[] };
    
        // Cache and Performance tools need the clients map
        if (ToolClass.name === "CacheTools" || ToolClass.name === "PerformanceTools") {
          toolInstance = new ToolClass(this.wordpressClients);
        } else {
          toolInstance = new (ToolClass as new () => { getTools(): unknown[] })();
        }
    
        const tools = toolInstance.getTools();
    
        tools.forEach((tool: unknown) => {
          this.registerTool(tool as ToolDefinition);
        });
      });
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does well by disclosing key behavioral traits: 'comprehensive validation and change tracking', 'All parameters except ID are optional - only provided fields will be updated', and specific behaviors like using 0 to remove featured media. It doesn't mention authentication needs or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with key information, but the extensive usage examples section (7 bullet points) could be more concise. While examples are helpful, they occupy significant space that might be better used for other guidance. The core description is efficient at 2 sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 10 parameters and no annotations/output schema, the description provides good context about the update behavior, validation, and partial updates. It covers the essential 'what happens' but could benefit from mentioning error conditions, permissions needed, or what the tool returns (success/failure indicators).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 10 parameters thoroughly. The description adds minimal value beyond what's in the schema - it emphasizes that only ID is required and other fields are optional, which is already implied by the required array. The usage examples show parameter combinations but don't add semantic meaning beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Updates' and resource 'existing WordPress post' with additional context about 'comprehensive validation and change tracking'. It distinguishes from sibling tools like wp_create_post (creates new) and wp_delete_post (deletes).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context about when to use this tool (updating existing posts) and includes usage examples for various scenarios. However, it doesn't explicitly state when NOT to use it or mention alternatives like wp_update_page for page updates.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/docdyhr/mcp-wordpress'

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