Skip to main content
Glama

backlog_list

List and filter backlog tasks by status, type, or search query to manage work items and track progress with customizable limits.

Instructions

List tasks from backlog. Returns most recently updated items first. Default: shows only active work (open/in_progress/blocked), limited to 20 items. Use counts=true to check if more items exist beyond the limit.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
statusNoFilter by status. Options: open, in_progress, blocked, done, cancelled. Default: [open, in_progress, blocked]. Pass ["done"] to see completed work.
typeNoFilter by type. Options: task, epic, folder, artifact, milestone. Default: returns all.
epic_idNoFilter tasks belonging to a specific epic. Example: epic_id="EPIC-0001"
parent_idNoFilter items by parent. Example: parent_id="FLDR-0001"
queryNoSearch across all task fields (title, description, evidence, references, etc.). Case-insensitive substring matching.
countsNoInclude global counts { total_tasks, total_epics, by_status, by_type } alongside results. Use this to detect if more items exist beyond the limit. Default: false
limitNoMax items to return. Default: 20. Increase if you need to see more items (e.g., limit=100 to list all epics).

Implementation Reference

  • Main handler function that executes the backlog_list tool logic. It filters tasks by status, type, epic_id, parent_id, and query parameters, then formats the results with optional counts.
    async ({ status, type, epic_id, parent_id, query, counts, limit }) => {
      // parent_id takes precedence; epic_id is alias for backward compat
      const resolvedParent = parent_id ?? epic_id;
      const tasks = await storage.list({ status, type, parent_id: resolvedParent, query, limit });
      const list = tasks.map((t) => ({
        id: t.id,
        title: t.title,
        status: t.status,
        type: t.type ?? 'task',
        parent_id: t.parent_id ?? t.epic_id,
      }));
      const result: any = { tasks: list };
      if (counts) result.counts = storage.counts();
      return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
    }
  • Zod input schema defining all filter parameters for backlog_list: status array, type enum, epic_id, parent_id, query string, counts boolean, and limit number.
    inputSchema: z.object({
      status: z.array(z.enum(STATUSES)).optional().describe('Filter by status. Options: open, in_progress, blocked, done, cancelled. Default: [open, in_progress, blocked]. Pass ["done"] to see completed work.'),
      type: z.enum(ENTITY_TYPES).optional().describe('Filter by type. Options: task, epic, folder, artifact, milestone. Default: returns all.'),
      epic_id: z.string().optional().describe('Filter tasks belonging to a specific epic. Example: epic_id="EPIC-0001"'),
      parent_id: z.string().optional().describe('Filter items by parent. Example: parent_id="FLDR-0001"'),
      query: z.string().optional().describe('Search across all task fields (title, description, evidence, references, etc.). Case-insensitive substring matching.'),
      counts: z.boolean().optional().describe('Include global counts { total_tasks, total_epics, by_status, by_type } alongside results. Use this to detect if more items exist beyond the limit. Default: false'),
      limit: z.number().optional().describe('Max items to return. Default: 20. Increase if you need to see more items (e.g., limit=100 to list all epics).'),
    }),
  • Tool registration function that registers 'backlog_list' with the MCP server, including the tool description and input schema.
    export function registerBacklogListTool(server: McpServer) {
      server.registerTool(
        'backlog_list',
        {
          description: 'List tasks from backlog. Returns most recently updated items first. Default: shows only active work (open/in_progress/blocked), limited to 20 items. Use counts=true to check if more items exist beyond the limit.',
          inputSchema: z.object({
            status: z.array(z.enum(STATUSES)).optional().describe('Filter by status. Options: open, in_progress, blocked, done, cancelled. Default: [open, in_progress, blocked]. Pass ["done"] to see completed work.'),
            type: z.enum(ENTITY_TYPES).optional().describe('Filter by type. Options: task, epic, folder, artifact, milestone. Default: returns all.'),
            epic_id: z.string().optional().describe('Filter tasks belonging to a specific epic. Example: epic_id="EPIC-0001"'),
            parent_id: z.string().optional().describe('Filter items by parent. Example: parent_id="FLDR-0001"'),
            query: z.string().optional().describe('Search across all task fields (title, description, evidence, references, etc.). Case-insensitive substring matching.'),
            counts: z.boolean().optional().describe('Include global counts { total_tasks, total_epics, by_status, by_type } alongside results. Use this to detect if more items exist beyond the limit. Default: false'),
            limit: z.number().optional().describe('Max items to return. Default: 20. Increase if you need to see more items (e.g., limit=100 to list all epics).'),
          }),
        },
  • Storage service list method that handles the actual data retrieval, including both search-based and filter-based listing of entities.
    async list(filter?: { status?: Status[]; type?: EntityType; epic_id?: string; parent_id?: string; query?: string; limit?: number }): Promise<Entity[]> {
      const { query, ...storageFilter } = filter ?? {};
    
      if (query) {
        await this.ensureSearchReady();
        const results = await this.search.search(query, {
          filters: { status: storageFilter.status, type: storageFilter.type, epic_id: storageFilter.epic_id, parent_id: storageFilter.parent_id },
          limit: storageFilter.limit,
        });
        return results.map(r => ({ ...r.task, score: r.score }));
      }
    
      return this.taskStorage.list(storageFilter);
    }
  • Schema constants defining EntityType enum, ENTITY_TYPES array, and STATUSES array used as validation enums in backlog_list input schema.
    export enum EntityType {
      Task = 'task',
      Epic = 'epic',
      Folder = 'folder',
      Artifact = 'artifact',
      Milestone = 'milestone',
    }
    
    export const ENTITY_TYPES = Object.values(EntityType);
    
    export const TYPE_PREFIXES: Record<EntityType, string> = {
      [EntityType.Task]: 'TASK',
      [EntityType.Epic]: 'EPIC',
      [EntityType.Folder]: 'FLDR',
      [EntityType.Artifact]: 'ARTF',
      [EntityType.Milestone]: 'MLST',
    };
    
    const PREFIX_TO_TYPE: Record<string, EntityType> = Object.fromEntries(
      Object.entries(TYPE_PREFIXES).map(([type, prefix]) => [prefix, type as EntityType]),
    ) as Record<string, EntityType>;
    
    // ============================================================================
    // Status
    // ============================================================================
    
    export const STATUSES = ['open', 'in_progress', 'blocked', 'done', 'cancelled'] as const;
    export type Status = (typeof STATUSES)[number];
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behaviors: sorting order ('most recently updated items first'), default filtering ('active work'), pagination-like limits ('limited to 20 items'), and the purpose of counts=true. It covers read-only listing adequately but lacks details on error handling or authentication needs.

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

Conciseness5/5

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

The description is front-loaded with core functionality and structured efficiently in three sentences. Each sentence adds value: the first states purpose and sorting, the second covers defaults, and the third explains counts usage. There is no wasted text, making it highly concise and well-organized.

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?

Given the complexity of 7 parameters and no output schema, the description provides good context for a read-only listing tool. It explains defaults, sorting, and how to detect more items, which is sufficient for basic usage. However, it lacks details on output format or error scenarios, leaving minor gaps in 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 the schema already documents all 7 parameters thoroughly. The description adds minimal parameter semantics beyond the schema, only mentioning counts=true and the default limit. This meets the baseline of 3 since the schema does the heavy lifting, but the description doesn't significantly enhance parameter understanding.

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 ('List') and resource ('tasks from backlog'), specifying the scope as 'most recently updated items first' and distinguishing it from siblings like backlog_search (which likely offers different filtering) and backlog_get (which retrieves a single item). This provides specific differentiation beyond just the name.

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 on when to use this tool: for listing backlog tasks with default filters (active work, 20 items) and when to use counts=true to check for more items. However, it does not explicitly mention when to use alternatives like backlog_search or backlog_get, leaving some sibling differentiation implicit rather than explicit.

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/gkoreli/backlog-mcp'

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