Skip to main content
Glama

epic_update

Idempotent

Update an epic by passing only the fields you want to change. Set status to cancelled to soft-delete, or use the branch parameter to pin to the active branch.

Instructions

Update an epic. Pass only the fields you want to change. Set status to "cancelled" to soft-delete. Pass branch="current" to pin to the active branch, or empty string to clear.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesEpic ID
nameNo
descriptionNo
statusNo
priorityNo
sort_orderNo
branchNoGit branch this epic is scoped to. Pass "current" to auto-detect; pass empty string to clear (branch-agnostic).
tagsNo

Implementation Reference

  • Core handler function for epic_update. Fetches the existing epic, resolves branch, builds an UPDATE SQL via buildUpdate helper, executes it, logs changes with logEntityUpdate, and returns the updated row.
    function handleEpicUpdate(args: Record<string, unknown>) {
      const db = getDb();
      const id = args.id as number;
    
      const oldRow = db.prepare('SELECT * FROM epics WHERE id = ?').get(id) as Record<string, unknown> | undefined;
      if (!oldRow) throw new Error(`Epic ${id} not found`);
    
      // Branch is handled separately so that explicit null/empty clears it; buildUpdate skips undefined.
      const branchResolution = args.branch !== undefined ? resolveBranch(args.branch) : undefined;
      const fieldsForBuilder: Record<string, unknown> = { ...args };
      if (branchResolution !== undefined) {
        fieldsForBuilder.branch = branchResolution;
      } else {
        delete fieldsForBuilder.branch;
      }
    
      const update = buildUpdate('epics', id, fieldsForBuilder, ['name', 'description', 'status', 'priority', 'sort_order', 'branch', 'tags']);
      if (!update) throw new Error('No fields to update');
    
      const newRow = db.prepare(update.sql).get(...update.params) as Record<string, unknown>;
      logEntityUpdate(db, 'epic', id, newRow.name as string, oldRow, newRow, ['name', 'status', 'priority', 'branch']);
    
      return newRow;
    }
  • Tool definition and input schema for epic_update. Declares the tool name, description, annotations, and inputSchema with updatable fields: id (required), name, description, status, priority, sort_order, branch, and tags.
    {
      name: 'epic_update',
      description:
        'Update an epic. Pass only the fields you want to change. Set status to "cancelled" to soft-delete. Pass branch="current" to pin to the active branch, or empty string to clear.',
      annotations: { title: 'Update Epic', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
      inputSchema: {
        type: 'object',
        properties: {
          id: { type: 'integer', description: 'Epic ID' },
          name: { type: 'string' },
          description: { type: 'string' },
          status: { type: 'string', enum: ['planned', 'in_progress', 'completed', 'cancelled'] },
          priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
          sort_order: { type: 'integer' },
          branch: {
            type: 'string',
            description: 'Git branch this epic is scoped to. Pass "current" to auto-detect; pass empty string to clear (branch-agnostic).',
          },
          tags: { type: 'array', items: { type: 'string' } },
        },
        required: ['id'],
      },
    },
  • src/index.ts:37-49 (registration)
    Registration of all tool handlers including epicHandlers which contains epic_update mapped to handleEpicUpdate.
    const ALL_HANDLERS: Record<string, (args: Record<string, unknown>) => unknown> = {
      ...projectHandlers,
      ...epicHandlers,
      ...taskHandlers,
      ...subtaskHandlers,
      ...noteHandlers,
      ...commentHandlers,
      ...templateHandlers,
      ...dashboardHandlers,
      ...searchHandlers,
      ...activityHandlers,
      ...exportImportHandlers,
    };
  • Export of the epic handlers map where 'epic_update' is mapped to the handleEpicUpdate function.
    export const handlers: Record<string, ToolHandler> = {
      epic_create: handleEpicCreate,
      epic_list: handleEpicList,
      epic_update: handleEpicUpdate,
    };
  • The buildUpdate helper used by handleEpicUpdate to dynamically construct an UPDATE SQL statement with only the provided fields.
    export function buildUpdate(
      table: string,
      id: number,
      fields: Record<string, unknown>,
      allowedColumns: string[]
    ): { sql: string; params: unknown[] } | null {
      const updates: string[] = [];
      const params: unknown[] = [];
    
      for (const col of allowedColumns) {
        if (fields[col] !== undefined) {
          updates.push(`${col} = ?`);
          params.push(JSON_COLUMNS.has(col) ? JSON.stringify(fields[col]) : fields[col]);
        }
      }
    
      if (updates.length === 0) return null;
    
      updates.push("updated_at = datetime('now')");
      params.push(id);
    
      return {
        sql: `UPDATE ${table} SET ${updates.join(', ')} WHERE id = ? RETURNING *`,
        params,
      };
    }
Behavior4/5

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

Annotations are readOnlyHint=false, destructiveHint=false, idempotentHint=true. The description adds crucial behavior: soft-delete via 'cancelled' status, and branch pinning/clearing. No contradictions.

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?

Three concise sentences with no filler. The most critical information is front-loaded: 'Update an epic.' Each subsequent sentence adds clear value.

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 8 parameters with enums and no output schema, the description covers key behaviors: partial updates, soft-delete, and branch handling. It lacks details on return values or error conditions but is adequately complete for an update tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25% (id and branch have descriptions). The description compensates by explaining the soft-delete effect of status and the special 'current' value for branch. It does not cover all parameters but adds meaningful context.

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 'Update an epic' with a specific verb and resource. It distinguishes from sibling tools like epic_create and epic_list by focusing on update semantics. It also adds unique details like partial updates and soft-delete.

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?

It gives explicit guidance: 'Pass only the fields you want to change.' It also explains special values for status and branch. However, it does not contrast with sibling tools like epic_create or mention prerequisites.

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/spranab/saga-mcp'

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