Skip to main content
Glama
posts.mjs6.92 kB
import { z } from "zod"; import { stringOrNumber, stringOrNumberArray, stringOrRaw, yoastMeta, } from "../schemas.mjs"; import { toolResult } from "../toolResult.mjs"; import { isWpError, wpErrorToolResult } from "../wpErrors.mjs"; import { buildQuery, buildYoastMeta, parseStatusOverride } from "../wpUtils.mjs"; // Registers post/CPT tools with dynamic post type routing. export function registerPostTools( server, { wpFetch, writePostLike, updatePostLike, resolvePostType } ) { server.tool( "list_posts", "List WordPress posts", { per_page: stringOrNumber.optional(), page: stringOrNumber.optional(), search: z.string().optional(), status: z.string().optional(), type: z.string().optional(), post_type: z.string().optional(), categories: stringOrNumberArray.optional(), tags: stringOrNumberArray.optional(), categories_exclude: stringOrNumberArray.optional(), tags_exclude: stringOrNumberArray.optional(), }, async ({ per_page = 10, page, search, status, type, post_type, categories, tags, categories_exclude, tags_exclude, } = {}) => { const postType = await resolvePostType(post_type || type); const query = buildQuery({ per_page, page, search, status, categories, tags, categories_exclude, tags_exclude, }); const posts = await wpFetch(`/wp-json/wp/v2/${postType}${query}`); if (isWpError(posts)) { return wpErrorToolResult(posts); } return toolResult({ posts }); } ); server.tool( "get_post", "Get a WordPress post by ID", { id: stringOrNumber, type: z.string().optional(), post_type: z.string().optional(), }, async ({ id, type, post_type } = {}) => { const postType = await resolvePostType(post_type || type); const post = await wpFetch(`/wp-json/wp/v2/${postType}/${id}`); if (isWpError(post)) { return wpErrorToolResult(post); } return toolResult({ post }); } ); server.tool( "create_post", "Create a WordPress post (draft by default)", { title: stringOrRaw.optional(), content: stringOrRaw.optional(), status: z.string().optional(), excerpt: stringOrRaw.optional(), slug: z.string().optional(), type: z.string().optional(), post_type: z.string().optional(), categories: stringOrNumberArray.optional(), tags: stringOrNumberArray.optional(), yoast: yoastMeta.optional(), }, async ({ title, content, status, excerpt, slug, type, post_type, categories, tags, yoast, } = {}) => { console.error("MCP: create_post called with:", { title, content, status, excerpt, slug, type, post_type, categories, tags, yoast, }); const parsedStatus = parseStatusOverride(status); const postType = await resolvePostType( post_type || type || parsedStatus.postType ); const resolvedStatus = parsedStatus.status ?? "draft"; const post = await writePostLike(`/wp-json/wp/v2/${postType}`, { title, content, status: resolvedStatus, excerpt, slug, categories, tags, meta: buildYoastMeta(yoast), }); if (isWpError(post)) { return wpErrorToolResult(post); } return toolResult({ post }); } ); server.tool( "create_announcement", "Create a WordPress announcement (draft by default)", { title: stringOrRaw.optional(), content: stringOrRaw.optional(), status: z.string().optional(), excerpt: stringOrRaw.optional(), slug: z.string().optional(), type: z.string().optional(), post_type: z.string().optional(), yoast: yoastMeta.optional(), }, async ({ title, content, status = "draft", excerpt, slug, type, post_type, yoast, } = {}) => { console.error("MCP: create_announcement called with:", { title, content, status, excerpt, slug, type, post_type, yoast, }); const postType = await resolvePostType(post_type || type || "announcement"); const announcement = await writePostLike(`/wp-json/wp/v2/${postType}`, { title, content, status, excerpt, slug, meta: buildYoastMeta(yoast), }); if (isWpError(announcement)) { return wpErrorToolResult(announcement); } return toolResult({ announcement }); } ); server.tool( "update_post", "Update a WordPress post", { id: stringOrNumber, title: stringOrRaw.optional(), content: stringOrRaw.optional(), status: z.string().optional(), excerpt: stringOrRaw.optional(), slug: z.string().optional(), type: z.string().optional(), post_type: z.string().optional(), categories: stringOrNumberArray.optional(), tags: stringOrNumberArray.optional(), yoast: yoastMeta.optional(), }, async ({ id, title, content, status, excerpt, slug, type, post_type, categories, tags, yoast, } = {}) => { console.error("MCP: update_post called with:", { id, title, content, status, excerpt, slug, type, post_type, categories, tags, yoast, }); const parsedStatus = parseStatusOverride(status); const postType = await resolvePostType( post_type || type || parsedStatus.postType ); const post = await updatePostLike(`/wp-json/wp/v2/${postType}/${id}`, { title, content, status: parsedStatus.status, excerpt, slug, categories, tags, meta: buildYoastMeta(yoast), }); if (isWpError(post)) { return wpErrorToolResult(post); } return toolResult({ post }); } ); server.tool( "delete_post", "Delete a WordPress post", { id: stringOrNumber, force: z.boolean().optional(), type: z.string().optional(), post_type: z.string().optional(), }, async ({ id, force = false, type, post_type } = {}) => { const postType = await resolvePostType(post_type || type); const query = buildQuery({ force }); const result = await wpFetch(`/wp-json/wp/v2/${postType}/${id}${query}`, { method: "DELETE", }); if (isWpError(result)) { return wpErrorToolResult(result); } return toolResult({ result }); } ); }

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

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