list-posts
Retrieve and filter WordPress posts by parameters like author, date, status, or search term using secure API authentication. Manage post collections programmatically with pagination and sorting options.
Instructions
Get a list of posts with comprehensive filtering options
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | Limit response to posts published after a given ISO8601 compliant date | |
| author | No | Limit result set to posts assigned to specific authors | |
| authorExclude | No | Ensure result set excludes posts assigned to specific authors | |
| before | No | Limit response to posts published before a given ISO8601 compliant date | |
| categories | No | Limit result set to items with specific terms assigned in the categories taxonomy | |
| categoriesExclude | No | Limit result set to items except those with specific terms assigned in the categories taxonomy | |
| context | No | Scope under which the request is made | view |
| exclude | No | Ensure result set excludes specific IDs | |
| include | No | Limit result set to specific IDs | |
| modifiedAfter | No | Limit response to posts modified after a given ISO8601 compliant date | |
| modifiedBefore | No | Limit response to posts modified before a given ISO8601 compliant date | |
| offset | No | Offset the result set by a specific number of items | |
| order | No | Order sort attribute ascending or descending | desc |
| orderby | No | Sort collection by post attribute | date |
| page | No | Current page of the collection | |
| password | Yes | WordPress application password | |
| perPage | No | Maximum number of items to be returned | |
| search | No | Limit results to those matching a string | |
| searchColumns | No | Array of column names to be searched | |
| siteUrl | Yes | WordPress site URL | |
| slug | No | Limit result set to posts with one or more specific slugs | |
| status | No | Limit result set to posts assigned one or more statuses | |
| sticky | No | Limit result set to items that are sticky | |
| tags | No | Limit result set to items with specific terms assigned in the tags taxonomy | |
| tagsExclude | No | Limit result set to items except those with specific terms assigned in the tags taxonomy | |
| taxRelation | No | Limit result set based on relationship between multiple taxonomies | |
| username | Yes | WordPress username |
Implementation Reference
- src/index.ts:601-699 (handler)The main handler function that executes the list-posts tool: constructs API parameters from inputs, calls the WordPress REST API /posts endpoint, formats the WPPost objects into a readable list, and returns a text response.async ({ siteUrl, username, password, context, page, perPage, search, after, modifiedAfter, author, authorExclude, before, modifiedBefore, exclude, include, offset, order, orderby, searchColumns, slug, status, taxRelation, categories, categoriesExclude, tags, tagsExclude, sticky, }) => { try { const params: Record<string, any> = { context, page, per_page: perPage, order, orderby, status: status?.join(','), }; if (search) params.search = search; if (after) params.after = after; if (modifiedAfter) params.modified_after = modifiedAfter; if (author) params.author = author.join(','); if (authorExclude) params.author_exclude = authorExclude.join(','); if (before) params.before = before; if (modifiedBefore) params.modified_before = modifiedBefore; if (exclude) params.exclude = exclude.join(','); if (include) params.include = include.join(','); if (offset) params.offset = offset; if (searchColumns) params.search_columns = searchColumns.join(','); if (slug) params.slug = slug.join(','); if (taxRelation) params.tax_relation = taxRelation; if (categories) params.categories = categories.join(','); if (categoriesExclude) params.categories_exclude = categoriesExclude.join(','); if (tags) params.tags = tags.join(','); if (tagsExclude) params.tags_exclude = tagsExclude.join(','); if (sticky !== undefined) params.sticky = sticky; const posts = await makeWPRequest<WPPost[]>({ siteUrl, endpoint: "posts", auth: { username, password }, params }); const formattedPosts = Array.isArray(posts) ? posts.map(post => ({ id: post.id, title: post.title?.rendered || "No title", date: post.date || "No date", status: post.status || "unknown", author: post.author || "Unknown", excerpt: post.excerpt?.rendered || "No excerpt" })) : []; const postsText = formattedPosts.length > 0 ? formattedPosts.map(post => `ID: ${post.id}\nTitle: ${post.title}\nDate: ${post.date}\nStatus: ${post.status}\nAuthor: ${post.author}\nExcerpt: ${post.excerpt}\n---` ).join("\n") : "No posts found"; return { content: [ { type: "text", text: `Posts from ${siteUrl}:\n\n${postsText}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error retrieving posts: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }
- src/index.ts:572-600 (schema)Zod schema for input validation of the list-posts tool, supporting comprehensive WordPress post filtering (pagination, search, date ranges, authors, categories, tags, status, etc.).{ siteUrl: z.string().url().describe("WordPress site URL"), username: z.string().describe("WordPress username"), password: z.string().describe("WordPress application password"), context: z.enum(["view", "embed", "edit"]).optional().default("view").describe("Scope under which the request is made"), page: z.number().min(1).optional().default(1).describe("Current page of the collection"), perPage: z.number().min(1).max(100).optional().default(10).describe("Maximum number of items to be returned"), search: z.string().optional().describe("Limit results to those matching a string"), after: z.string().optional().describe("Limit response to posts published after a given ISO8601 compliant date"), modifiedAfter: z.string().optional().describe("Limit response to posts modified after a given ISO8601 compliant date"), author: z.array(z.number()).optional().describe("Limit result set to posts assigned to specific authors"), authorExclude: z.array(z.number()).optional().describe("Ensure result set excludes posts assigned to specific authors"), before: z.string().optional().describe("Limit response to posts published before a given ISO8601 compliant date"), modifiedBefore: z.string().optional().describe("Limit response to posts modified before a given ISO8601 compliant date"), exclude: z.array(z.number()).optional().describe("Ensure result set excludes specific IDs"), include: z.array(z.number()).optional().describe("Limit result set to specific IDs"), offset: z.number().optional().describe("Offset the result set by a specific number of items"), order: z.enum(["asc", "desc"]).optional().default("desc").describe("Order sort attribute ascending or descending"), orderby: z.enum(["author", "date", "id", "include", "modified", "parent", "relevance", "slug", "include_slugs", "title"]).optional().default("date").describe("Sort collection by post attribute"), searchColumns: z.array(z.string()).optional().describe("Array of column names to be searched"), slug: z.array(z.string()).optional().describe("Limit result set to posts with one or more specific slugs"), status: z.array(z.enum(["publish", "future", "draft", "pending", "private"])).optional().default(["publish"]).describe("Limit result set to posts assigned one or more statuses"), taxRelation: z.enum(["AND", "OR"]).optional().describe("Limit result set based on relationship between multiple taxonomies"), categories: z.array(z.number()).optional().describe("Limit result set to items with specific terms assigned in the categories taxonomy"), categoriesExclude: z.array(z.number()).optional().describe("Limit result set to items except those with specific terms assigned in the categories taxonomy"), tags: z.array(z.number()).optional().describe("Limit result set to items with specific terms assigned in the tags taxonomy"), tagsExclude: z.array(z.number()).optional().describe("Limit result set to items except those with specific terms assigned in the tags taxonomy"), sticky: z.boolean().optional().describe("Limit result set to items that are sticky"), },
- src/index.ts:569-571 (registration)MCP server registration of the 'list-posts' tool, specifying name, description, input schema, and handler function.server.tool( "list-posts", "Get a list of posts with comprehensive filtering options",
- src/index.ts:10-57 (helper)TypeScript interface defining the structure of WordPress post objects returned by the API and used in the handler.interface WPPost { id: number; date?: string; date_gmt?: string; guid?: { rendered: string; }; modified?: string; modified_gmt?: string; slug?: string; status?: 'publish' | 'future' | 'draft' | 'pending' | 'private'; type?: string; link?: string; title?: { rendered: string; }; content?: { rendered: string; protected?: boolean; }; excerpt?: { rendered: string; protected?: boolean; }; author?: number; featured_media?: number; comment_status?: 'open' | 'closed'; ping_status?: 'open' | 'closed'; sticky?: boolean; template?: string; format?: 'standard' | 'aside' | 'chat' | 'gallery' | 'link' | 'image' | 'quote' | 'status' | 'video' | 'audio'; meta?: Record<string, any>; _links?: { self?: Array<{ href: string }>; collection?: Array<{ href: string }>; about?: Array<{ href: string }>; author?: Array<{ href: string; embeddable: boolean }>; replies?: Array<{ href: string; embeddable: boolean }>; 'version-history'?: Array<{ href: string }>; 'predecessor-version'?: Array<{ href: string; id: number }>; 'wp:featuredmedia'?: Array<{ href: string; embeddable: boolean }>; 'wp:attachment'?: Array<{ href: string }>; 'wp:term'?: Array<{ href: string; taxonomy: string; embeddable: boolean }>; curies?: Array<{ name: string; href: string; templated: boolean }>; }; categories?: number[]; tags?: number[]; }
- src/index.ts:158-194 (helper)Reusable helper function for authenticated HTTP requests to the WordPress REST API v2, used by all tools including list-posts.async function makeWPRequest<T>({ siteUrl, endpoint, method = 'GET', auth, data = null, params = null }: { siteUrl: string; endpoint: string; method?: 'GET' | 'POST' | 'PUT' | 'DELETE'; auth: { username: string; password: string }; data?: any; params?: any; }): Promise<T> { const authString = Buffer.from(`${auth.username}:${auth.password}`).toString('base64'); try { const response = await axios({ method, url: `${siteUrl}/wp-json/wp/v2/${endpoint}`, headers: { 'Authorization': `Basic ${authString}`, 'Content-Type': 'application/json', }, data: data, params: params }); return response.data as T; } catch (error) { if (axios.isAxiosError(error) && error.response) { throw new Error(`WordPress API error: ${error.response.data?.message || error.message}`); } throw error; } }