MW
Tutorial 11 min read

Building a create-post MCP tool

Schema, validation, permissions, request/response, error mapping — a complete tool walkthrough.

Tool Posts Validation Permissions
Agent
posts.create
WP REST

1. Overview

The simplest useful WP-MCP tool: take a title + content + optional status, post it, return the new post's id and url.

2. Input schema

tools/posts.create.ts typescript
import { z } from 'zod'

export const PostsCreateInput = z.object({
  title:   z.string().min(1).max(160),
  content: z.string().min(1),
  status:  z.enum(['draft', 'publish', 'private']).default('draft'),
  excerpt: z.string().max(280).optional(),
  tags:    z.array(z.string()).max(20).optional(),
})

3. Validation & permissions

4. Implementation

Request
request.json json
{
  "method": "tools/call",
  "params": {
    "name": "posts.create",
    "arguments": {
      "title":  "Hello world",
      "content":"Body of the post",
      "status": "draft"
    }
  }
}
Response
response.json json
{
  "content": [
    { "type":"text", "text":"Created post #128: https://example.com/?p=128" }
  ]
}

5. Error handling

Return a structured isError: true with content describing the failure. Don't let the agent guess from HTTP codes.

6. Testing the tool

test/posts.create.test.ts typescript
import { describe, it, expect } from 'vitest'
import { handle } from '../src/tools/posts.create'

describe('posts.create', () => {
  it('rejects missing title', async () => {
    const r = await handle({ content: 'x' } as any)
    expect(r.isError).toBe(true)
  })
})

One tool, shipped

Schema → handler → tests. Repeat for every WP verb.

  • Typed
  • Validated
  • Tested