linear_convertIssueToSubtask
Convert a Linear issue into a subtask by linking it to a parent issue for better project organization and hierarchy management.
Instructions
Convert an issue to a subtask
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueId | Yes | ID or identifier of the issue to convert (e.g., ABC-123) | |
| parentIssueId | Yes | ID or identifier of the parent issue (e.g., ABC-456) |
Implementation Reference
- The handler function that executes the tool logic: validates input arguments using a type guard and calls the LinearService.convertIssueToSubtask method to perform the conversion.export function handleConvertIssueToSubtask(linearService: LinearService) { return async (args: unknown) => { try { if (!isConvertIssueToSubtaskArgs(args)) { throw new Error("Invalid arguments for convertIssueToSubtask"); } return await linearService.convertIssueToSubtask(args.issueId, args.parentIssueId); } catch (error) { logError("Error converting issue to subtask", error); throw error; } }; }
- The MCP tool definition/schema specifying the tool name, description, input schema (issueId and parentIssueId required), and output schema.export const convertIssueToSubtaskToolDefinition: MCPToolDefinition = { name: "linear_convertIssueToSubtask", description: "Convert an issue to a subtask", input_schema: { type: "object", properties: { issueId: { type: "string", description: "ID or identifier of the issue to convert (e.g., ABC-123)", }, parentIssueId: { type: "string", description: "ID or identifier of the parent issue (e.g., ABC-456)", }, }, required: ["issueId", "parentIssueId"], }, output_schema: { type: "object", properties: { success: { type: "boolean" }, issue: { type: "object", properties: { id: { type: "string" }, identifier: { type: "string" }, title: { type: "string" }, parent: { type: "object" }, url: { type: "string" } } } } } };
- src/tools/handlers/index.ts:90-90 (registration)Registration of the tool in the handlers map returned by registerToolHandlers function, mapping tool name to the handler instance.linear_convertIssueToSubtask: handleConvertIssueToSubtask(linearService),
- src/tools/type-guards.ts:282-295 (helper)Type guard function used by the handler to validate the tool's input arguments (issueId and parentIssueId as strings).*/ export function isConvertIssueToSubtaskArgs(args: unknown): args is { issueId: string; parentIssueId: string; } { return ( typeof args === "object" && args !== null && "issueId" in args && typeof (args as { issueId: string }).issueId === "string" && "parentIssueId" in args && typeof (args as { parentIssueId: string }).parentIssueId === "string" ); }
- LinearService method implementing the core logic: fetches issues, updates the issue's parentId using Linear SDK, and returns formatted success response with updated issue data.async convertIssueToSubtask(issueId: string, parentIssueId: string) { try { // Get both issues const issue = await this.client.issue(issueId); if (!issue) { throw new Error(`Issue with ID ${issueId} not found`); } const parentIssue = await this.client.issue(parentIssueId); if (!parentIssue) { throw new Error(`Parent issue with ID ${parentIssueId} not found`); } // Convert the issue to a subtask const updatedIssue = await issue.update({ parentId: parentIssueId, }); // Get parent data - we need to fetch the updated issue to get relationships const updatedIssueData = await this.client.issue(issue.id); const parentData = updatedIssueData && updatedIssueData.parent ? await updatedIssueData.parent : null; return { success: true, issue: { id: issue.id, identifier: issue.identifier, title: issue.title, parent: parentData ? { id: parentData.id, identifier: parentData.identifier, title: parentData.title, } : null, url: issue.url, }, }; } catch (error) { console.error('Error converting issue to subtask:', error); throw error; } }