Skip to main content
Glama

list-categories

Retrieve and filter WordPress categories by ID, slug, parent, or post using secure API authentication. Manage and organize site content efficiently with customizable sorting and pagination options.

Instructions

Get a list of categories with filtering options

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contextNoScope under which the request is madeview
excludeNoEnsure result set excludes specific IDs
hideEmptyNoWhether to hide terms not assigned to any posts
includeNoLimit result set to specific IDs
orderNoOrder sort attribute ascending or descendingasc
orderbyNoSort collection by term attributename
pageNoCurrent page of the collection
parentNoLimit result set to terms assigned to a specific parent
passwordYesWordPress application password
perPageNoMaximum number of items to be returned
postNoLimit result set to terms assigned to a specific post
searchNoLimit results to those matching a string
siteUrlYesWordPress site URL
slugNoLimit result set to terms with one or more specific slugs
usernameYesWordPress username

Implementation Reference

  • Handler function that constructs API parameters from inputs, calls makeWPRequest to fetch categories from /wp-json/wp/v2/categories, formats the results into a readable text list, and returns as MCP content or error.
    async ({ 
      siteUrl, 
      username, 
      password,
      context,
      page,
      perPage,
      search,
      exclude,
      include,
      order,
      orderby,
      hideEmpty,
      parent,
      post,
      slug,
    }) => {
      try {
        const params: Record<string, any> = {
          context,
          page,
          per_page: perPage,
          order,
          orderby,
        };
    
        if (search) params.search = search;
        if (exclude) params.exclude = exclude.join(',');
        if (include) params.include = include.join(',');
        if (hideEmpty !== undefined) params.hide_empty = hideEmpty;
        if (parent) params.parent = parent;
        if (post) params.post = post;
        if (slug) params.slug = slug.join(',');
    
        const categories = await makeWPRequest<WPCategory[]>({
          siteUrl,
          endpoint: "categories",
          auth: { username, password },
          params
        });
        
        const formattedCategories = Array.isArray(categories) ? categories.map(category => ({
          id: category.id,
          name: category.name || "No name",
          slug: category.slug || "No slug",
          description: category.description || "No description",
          parent: category.parent || 0,
          count: category.count || 0
        })) : [];
        
        const categoriesText = formattedCategories.length > 0
          ? formattedCategories.map(category => 
              `ID: ${category.id}\nName: ${category.name}\nSlug: ${category.slug}\nDescription: ${category.description}\nParent ID: ${category.parent}\nPost Count: ${category.count}\n---`
            ).join("\n")
          : "No categories found";
        
        return {
          content: [
            {
              type: "text",
              text: `Categories from ${siteUrl}:\n\n${categoriesText}`,
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error retrieving categories: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
        };
      }
    }
  • Zod schema for input parameters including authentication details and comprehensive WP categories filtering options (pagination, search, ordering, hierarchy, 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"),
      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"),
      order: z.enum(["asc", "desc"]).optional().default("asc").describe("Order sort attribute ascending or descending"),
      orderby: z.enum(["id", "include", "name", "slug", "include_slugs", "term_group", "description", "count"]).optional().default("name").describe("Sort collection by term attribute"),
      hideEmpty: z.boolean().optional().describe("Whether to hide terms not assigned to any posts"),
      parent: z.number().optional().describe("Limit result set to terms assigned to a specific parent"),
      post: z.number().optional().describe("Limit result set to terms assigned to a specific post"),
      slug: z.array(z.string()).optional().describe("Limit result set to terms with one or more specific slugs"),
    },
  • src/index.ts:1785-1880 (registration)
    McpServer.tool registration for 'list-categories' tool, specifying name, description, input schema, and handler function.
    server.tool(
      "list-categories",
      "Get a list of categories with filtering options",
      {
        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"),
        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"),
        order: z.enum(["asc", "desc"]).optional().default("asc").describe("Order sort attribute ascending or descending"),
        orderby: z.enum(["id", "include", "name", "slug", "include_slugs", "term_group", "description", "count"]).optional().default("name").describe("Sort collection by term attribute"),
        hideEmpty: z.boolean().optional().describe("Whether to hide terms not assigned to any posts"),
        parent: z.number().optional().describe("Limit result set to terms assigned to a specific parent"),
        post: z.number().optional().describe("Limit result set to terms assigned to a specific post"),
        slug: z.array(z.string()).optional().describe("Limit result set to terms with one or more specific slugs"),
      },
      async ({ 
        siteUrl, 
        username, 
        password,
        context,
        page,
        perPage,
        search,
        exclude,
        include,
        order,
        orderby,
        hideEmpty,
        parent,
        post,
        slug,
      }) => {
        try {
          const params: Record<string, any> = {
            context,
            page,
            per_page: perPage,
            order,
            orderby,
          };
    
          if (search) params.search = search;
          if (exclude) params.exclude = exclude.join(',');
          if (include) params.include = include.join(',');
          if (hideEmpty !== undefined) params.hide_empty = hideEmpty;
          if (parent) params.parent = parent;
          if (post) params.post = post;
          if (slug) params.slug = slug.join(',');
    
          const categories = await makeWPRequest<WPCategory[]>({
            siteUrl,
            endpoint: "categories",
            auth: { username, password },
            params
          });
          
          const formattedCategories = Array.isArray(categories) ? categories.map(category => ({
            id: category.id,
            name: category.name || "No name",
            slug: category.slug || "No slug",
            description: category.description || "No description",
            parent: category.parent || 0,
            count: category.count || 0
          })) : [];
          
          const categoriesText = formattedCategories.length > 0
            ? formattedCategories.map(category => 
                `ID: ${category.id}\nName: ${category.name}\nSlug: ${category.slug}\nDescription: ${category.description}\nParent ID: ${category.parent}\nPost Count: ${category.count}\n---`
              ).join("\n")
            : "No categories found";
          
          return {
            content: [
              {
                type: "text",
                text: `Categories from ${siteUrl}:\n\n${categoriesText}`,
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `Error retrieving categories: ${error instanceof Error ? error.message : String(error)}`,
              },
            ],
          };
        }
      }
    );
  • TypeScript interface defining the shape of WordPress category objects used in type annotations for API responses.
    interface WPCategory {
      id: number;
      name?: string;
      slug?: string;
      description?: string;
      parent?: number;
      count?: number;
      meta?: Record<string, any>;
    }
  • Reusable helper for authenticated HTTP requests to WordPress REST API endpoints, used by list-categories handler to fetch data.
    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;
      }
    }
Behavior2/5

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

With no annotations, the description carries full burden but lacks behavioral details. It mentions 'filtering options' but doesn't disclose that this is a read-only list operation (implied by 'Get'), pagination behavior (via 'page' and 'perPage'), authentication requirements (siteUrl, username, password are required), or rate limits. It adds minimal context beyond the basic action.

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

Conciseness4/5

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

The description is a single, efficient sentence that front-loads the core action. However, it could be more specific (e.g., 'Get a paginated list of WordPress categories with filtering by ID, parent, search, etc.') to better earn its place without adding unnecessary length.

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

Completeness3/5

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

Given 15 parameters, no annotations, and no output schema, the description is minimally adequate but incomplete. It hints at filtering but doesn't cover authentication needs, pagination, or return format. For a complex tool with many parameters, more context (e.g., 'Requires WordPress credentials, returns paginated results') would improve completeness.

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 parameters are well-documented in the schema. The description adds little beyond mentioning 'filtering options', which loosely references parameters like 'exclude', 'include', 'search', etc., but doesn't explain their semantics or relationships. Baseline 3 is appropriate as the schema does the heavy lifting.

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

Purpose3/5

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

The description 'Get a list of categories with filtering options' clearly states the verb ('Get a list') and resource ('categories'), but it's vague about scope and doesn't differentiate from siblings like 'get-category' (singular) or 'list-posts'. It doesn't specify what kind of categories (e.g., WordPress taxonomy categories) or the full extent of filtering.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives. It doesn't mention when to choose 'list-categories' over 'get-category' (for a single category) or 'list-posts' (for posts instead of categories), nor does it specify prerequisites like authentication needs implied by required parameters.

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

Related 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/prathammanocha/wordpress-mcp-server'

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