update-story
Modify existing Shortcut stories by updating specific fields like name, description, type, or workflow state using the story's public ID.
Instructions
Update an existing Shortcut story. Only provide fields you want to update. The story public ID will always be included in updates.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| storyPublicId | Yes | The public ID of the story to update | |
| name | No | The name of the story | |
| description | No | The description of the story | |
| type | No | The type of the story | |
| epic | No | The epic id of the epic the story belongs to, or null to unset | |
| estimate | No | The point estimate of the story, or null to unset | |
| iteration | No | The iteration id of the iteration the story belongs to, or null to unset | |
| owner_ids | No | Array of user UUIDs to assign as owners of the story | |
| workflow_state_id | No | The workflow state ID to move the story to | |
| labels | No | Labels to assign to the story |
Implementation Reference
- src/tools/stories.ts:473-517 (handler)The handler function `updateStory` that executes the core logic of updating a Shortcut story based on provided parameters. It validates inputs, fetches the story, prepares update parameters, calls the client to update, and returns a result message.async updateStory({ storyPublicId, ...updates }: { storyPublicId: number; name?: string; description?: string; type?: "feature" | "bug" | "chore"; epic?: number | null; estimate?: number | null; iteration?: number | null; owner_ids?: string[]; workflow_state_id?: number; labels?: Array<{ name: string; color?: string; description?: string; }>; }) { if (!storyPublicId) throw new Error("Story public ID is required"); // Verify the story exists const story = await this.client.getStory(storyPublicId); if (!story) throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`); // Convert API parameters const updateParams: Record<string, unknown> = {}; if (updates.name !== undefined) updateParams.name = updates.name; if (updates.description !== undefined) updateParams.description = updates.description; if (updates.type !== undefined) updateParams.story_type = updates.type; if (updates.epic !== undefined) updateParams.epic_id = updates.epic; if (updates.estimate !== undefined) updateParams.estimate = updates.estimate; if (updates.iteration !== undefined) updateParams.iteration_id = updates.iteration; if (updates.owner_ids !== undefined) updateParams.owner_ids = updates.owner_ids; if (updates.workflow_state_id !== undefined) updateParams.workflow_state_id = updates.workflow_state_id; if (updates.labels !== undefined) updateParams.labels = updates.labels; // Update the story const updatedStory = await this.client.updateStory(storyPublicId, updateParams); return this.toResult(`Updated story sc-${storyPublicId}. Story URL: ${updatedStory.app_url}`); }
- src/tools/stories.ts:164-201 (schema)Input schema using Zod for validating parameters of the 'update-story' tool, including storyPublicId (required), and optional fields like name, description, type, epic, estimate, etc.storyPublicId: z.number().positive().describe("The public ID of the story to update"), name: z.string().max(512).optional().describe("The name of the story"), description: z.string().max(10_000).optional().describe("The description of the story"), type: z.enum(["feature", "bug", "chore"]).optional().describe("The type of the story"), epic: z .number() .nullable() .optional() .describe("The epic id of the epic the story belongs to, or null to unset"), estimate: z .number() .nullable() .optional() .describe("The point estimate of the story, or null to unset"), iteration: z .number() .nullable() .optional() .describe("The iteration id of the iteration the story belongs to, or null to unset"), owner_ids: z .array(z.string()) .optional() .describe("Array of user UUIDs to assign as owners of the story"), workflow_state_id: z .number() .optional() .describe("The workflow state ID to move the story to"), labels: z .array( z.object({ name: z.string().describe("The name of the label"), color: z.string().optional().describe("The color of the label"), description: z.string().optional().describe("The description of the label"), }), ) .optional() .describe("Labels to assign to the story"), },
- src/tools/stories.ts:160-203 (registration)Registration of the 'update-story' MCP tool using server.tool(), including name, description, input schema, and handler reference to tools.updateStory.server.tool( "update-story", "Update an existing Shortcut story. Only provide fields you want to update. The story public ID will always be included in updates.", { storyPublicId: z.number().positive().describe("The public ID of the story to update"), name: z.string().max(512).optional().describe("The name of the story"), description: z.string().max(10_000).optional().describe("The description of the story"), type: z.enum(["feature", "bug", "chore"]).optional().describe("The type of the story"), epic: z .number() .nullable() .optional() .describe("The epic id of the epic the story belongs to, or null to unset"), estimate: z .number() .nullable() .optional() .describe("The point estimate of the story, or null to unset"), iteration: z .number() .nullable() .optional() .describe("The iteration id of the iteration the story belongs to, or null to unset"), owner_ids: z .array(z.string()) .optional() .describe("Array of user UUIDs to assign as owners of the story"), workflow_state_id: z .number() .optional() .describe("The workflow state ID to move the story to"), labels: z .array( z.object({ name: z.string().describe("The name of the label"), color: z.string().optional().describe("The color of the label"), description: z.string().optional().describe("The description of the label"), }), ) .optional() .describe("Labels to assign to the story"), }, async (params) => await tools.updateStory(params), );