update_issue
Modify GitHub issue details including title, description, status, assignees, labels, and milestone to track project changes and maintain accurate task management.
Instructions
Update a GitHub issue
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueId | Yes | ||
| title | No | ||
| description | No | ||
| status | No | ||
| milestoneId | Yes | ||
| assignees | No | ||
| labels | No |
Input Schema (JSON Schema)
{
"properties": {
"assignees": {
"items": {
"type": "string"
},
"type": "array"
},
"description": {
"type": "string"
},
"issueId": {
"type": "string"
},
"labels": {
"items": {
"type": "string"
},
"type": "array"
},
"milestoneId": {
"type": "string"
},
"status": {
"enum": [
"open",
"closed"
]
},
"title": {
"type": "string"
}
},
"required": [
"issueId",
"milestoneId"
],
"type": "object"
}
Implementation Reference
- src/index.ts:284-292 (handler)Main tool handler in executeToolHandler switch statement. Maps tool arguments and delegates to ProjectManagementService.updateIssue method.case "update_issue": return await this.service.updateIssue(args.issueId, { title: args.title, description: args.description, status: args.status, milestoneId: args.milestoneId, assignees: args.assignees, labels: args.labels });
- Core business logic for updating GitHub issues. Maps input parameters to Issue partial, handles status conversion and milestone null handling, then delegates to GitHubIssueRepository.update.async updateIssue( issueId: string, updates: { title?: string; description?: string; status?: string; milestoneId?: string | null; assignees?: string[]; labels?: string[]; } ): Promise<Issue> { try { const data: Partial<Issue> = {}; if (updates.title) data.title = updates.title; if (updates.description) data.description = updates.description; if (updates.status) { data.status = updates.status === 'open' ? ResourceStatus.ACTIVE : ResourceStatus.CLOSED; } if (updates.assignees) data.assignees = updates.assignees; if (updates.labels) data.labels = updates.labels; // Handle milestoneId explicitly if (updates.milestoneId === null) { data.milestoneId = undefined; // Remove milestone } else if (updates.milestoneId !== undefined) { data.milestoneId = updates.milestoneId; } return await this.issueRepo.update(issueId, data); } catch (error) { throw this.mapErrorToMCPError(error); } }
- Zod schema definition for update_issue tool input validation (lines 166-176) and complete ToolDefinition including description and examples (380-395).// Schema for update_issue tool export const updateIssueSchema = z.object({ issueId: z.string().min(1, "Issue ID is required"), title: z.string().optional(), description: z.string().optional(), status: z.enum(["open", "closed"]).optional(), milestoneId: z.string().optional().nullable(), assignees: z.array(z.string()).optional(), labels: z.array(z.string()).optional(), }); export type UpdateIssueArgs = z.infer<typeof updateIssueSchema>; // Schema for create_sprint tool export const createSprintSchema = z.object({ title: z.string().min(1, "Sprint title is required"), description: z.string().min(1, "Sprint description is required"), startDate: z.string().datetime("Start date must be a valid ISO date string"), endDate: z.string().datetime("End date must be a valid ISO date string"), issueIds: z.array(z.string()).default([]), }); export type CreateSprintArgs = z.infer<typeof createSprintSchema>; // Schema for list_sprints tool export const listSprintsSchema = z.object({ status: z.enum(["planned", "active", "completed", "all"]).default("all"), }); export type ListSprintsArgs = z.infer<typeof listSprintsSchema>; // Schema for get_current_sprint tool export const getCurrentSprintSchema = z.object({ includeIssues: z.boolean().default(true), }); export type GetCurrentSprintArgs = z.infer<typeof getCurrentSprintSchema>; // Schema for create_project_field tool export const createProjectFieldSchema = z.object({ projectId: z.string().min(1, "Project ID is required"), name: z.string().min(1, "Field name is required"), type: z.enum([ "text", "number", "date", "single_select", "iteration", "milestone", "assignees", "labels" ]), options: z.array( z.object({ name: z.string().min(1), description: z.string().optional(), color: z.string().optional(), }) ).optional(), description: z.string().optional(), required: z.boolean().optional(), }); export type CreateProjectFieldArgs = z.infer<typeof createProjectFieldSchema>; // Schema for create_project_view tool export const createProjectViewSchema = z.object({ projectId: z.string().min(1, "Project ID is required"), name: z.string().min(1, "View name is required"), layout: z.enum(["board", "table", "timeline", "roadmap"]), }); export type CreateProjectViewArgs = z.infer<typeof createProjectViewSchema>; // Tool definitions with schemas, descriptions, and examples // Project tools export const createProjectTool: ToolDefinition<CreateProjectArgs> = { name: "create_project", description: "Create a new GitHub project", schema: createProjectSchema as unknown as ToolSchema<CreateProjectArgs>, examples: [ { name: "Create private project", description: "Create a new private GitHub project", args: { title: "Backend API Development", shortDescription: "Project for tracking backend API development tasks", owner: "example-owner", visibility: "private" } } ] }; export const listProjectsTool: ToolDefinition<ListProjectsArgs> = { name: "list_projects", description: "List GitHub projects", schema: listProjectsSchema as unknown as ToolSchema<ListProjectsArgs>, examples: [ { name: "List active projects", description: "List all active GitHub projects", args: { status: "active", limit: 5 } } ] }; export const getProjectTool: ToolDefinition<GetProjectArgs> = { name: "get_project", description: "Get details of a specific GitHub project", schema: getProjectSchema as unknown as ToolSchema<GetProjectArgs>, examples: [ { name: "Get project details", description: "Get details for a specific project", args: { projectId: "PVT_kwDOLhQ7gc4AOEbH" } } ] }; // Milestone tools export const createMilestoneTool: ToolDefinition<CreateMilestoneArgs> = { name: "create_milestone", description: "Create a new milestone", schema: createMilestoneSchema as unknown as ToolSchema<CreateMilestoneArgs>, examples: [ { name: "Create milestone with due date", description: "Create a milestone with title, description and due date", args: { title: "Beta Release", description: "Complete all features for beta release", dueDate: "2025-06-30T00:00:00Z" } } ] }; export const listMilestonesTool: ToolDefinition<ListMilestonesArgs> = { name: "list_milestones", description: "List milestones", schema: listMilestonesSchema as unknown as ToolSchema<ListMilestonesArgs>, examples: [ { name: "List open milestones", description: "List all open milestones sorted by due date", args: { status: "open", sort: "due_date", direction: "asc" } } ] }; // Issue tools export const createIssueTool: ToolDefinition<CreateIssueArgs> = { name: "create_issue", description: "Create a new GitHub issue", schema: createIssueSchema as unknown as ToolSchema<CreateIssueArgs>, examples: [ { name: "Create bug issue", description: "Create a bug issue with high priority", args: { title: "Fix authentication bug", description: "Users cannot log in with social media accounts", priority: "high", type: "bug", assignees: ["developer1"], labels: ["bug", "authentication"] } } ] }; export const listIssuesTool: ToolDefinition<ListIssuesArgs> = { name: "list_issues", description: "List GitHub issues", schema: listIssuesSchema as unknown as ToolSchema<ListIssuesArgs>, examples: [ { name: "List open issues for milestone", description: "List open issues assigned to a specific milestone", args: { status: "open", milestone: "1", sort: "updated", direction: "desc", limit: 10 } } ] }; export const getIssueTool: ToolDefinition<GetIssueArgs> = { name: "get_issue", description: "Get details of a specific GitHub issue", schema: getIssueSchema as unknown as ToolSchema<GetIssueArgs>, examples: [ { name: "Get issue details", description: "Get detailed information about an issue", args: { issueId: "42" } } ] }; export const updateIssueTool: ToolDefinition<UpdateIssueArgs> = { name: "update_issue", description: "Update a GitHub issue", schema: updateIssueSchema as unknown as ToolSchema<UpdateIssueArgs>, examples: [ { name: "Update issue status and milestone", description: "Close an issue and assign it to a milestone", args: { issueId: "42", status: "closed", milestoneId: "3" } } ] };
- src/infrastructure/tools/ToolRegistry.ts:17-158 (registration)Imports updateIssueTool from ToolSchemas and registers it in the central ToolRegistry singleton instance.getIssueTool, updateIssueTool, createSprintTool, listSprintsTool, getCurrentSprintTool, createProjectFieldTool, createProjectViewTool, // New project tools updateProjectTool, deleteProjectTool, listProjectFieldsTool, updateProjectFieldTool, // Project item tools addProjectItemTool, removeProjectItemTool, listProjectItemsTool, // Field values tools setFieldValueTool, getFieldValueTool, // View tools listProjectViewsTool, updateProjectViewTool, // Milestone tools updateMilestoneTool, deleteMilestoneTool, // Sprint tools updateSprintTool, addIssuesToSprintTool, removeIssuesFromSprintTool, // Label tools createLabelTool, listLabelsTool, // AI task management tools addFeatureTool, generatePRDTool, parsePRDTool, getNextTaskTool, analyzeTaskComplexityTool, expandTaskTool, enhancePRDTool, createTraceabilityMatrixTool, } from "./ToolSchemas.js"; /** * Central registry of all available tools */ export class ToolRegistry { private static _instance: ToolRegistry; private _tools: Map<string, ToolDefinition<any>>; private constructor() { this._tools = new Map(); this.registerBuiltInTools(); } /** * Get the singleton instance */ public static getInstance(): ToolRegistry { if (!ToolRegistry._instance) { ToolRegistry._instance = new ToolRegistry(); } return ToolRegistry._instance; } /** * Register a new tool */ public registerTool<T>(tool: ToolDefinition<T>): void { if (this._tools.has(tool.name)) { process.stderr.write(`Tool '${tool.name}' is already registered and will be overwritten.\n`); } this._tools.set(tool.name, tool); } /** * Get a tool by name */ public getTool<T>(name: string): ToolDefinition<T> | undefined { return this._tools.get(name) as ToolDefinition<T> | undefined; } /** * Get all registered tools */ public getAllTools(): ToolDefinition<any>[] { return Array.from(this._tools.values()); } /** * Convert tools to MCP format for list_tools response */ public getToolsForMCP(): Array<{ name: string; description: string; inputSchema: any; }> { return this.getAllTools().map(tool => ({ name: tool.name, description: tool.description, inputSchema: this.convertZodToJsonSchema(tool.schema), })); } /** * Register all built-in tools */ private registerBuiltInTools(): void { // Register roadmap and planning tools this.registerTool(createRoadmapTool); this.registerTool(planSprintTool); this.registerTool(getMilestoneMetricsTool); this.registerTool(getSprintMetricsTool); this.registerTool(getOverdueMilestonesTool); this.registerTool(getUpcomingMilestonesTool); // Register project tools this.registerTool(createProjectTool); this.registerTool(listProjectsTool); this.registerTool(getProjectTool); this.registerTool(updateProjectTool); this.registerTool(deleteProjectTool); // Register milestone tools this.registerTool(createMilestoneTool); this.registerTool(listMilestonesTool); this.registerTool(updateMilestoneTool); this.registerTool(deleteMilestoneTool); // Register issue tools this.registerTool(createIssueTool); this.registerTool(listIssuesTool); this.registerTool(getIssueTool); this.registerTool(updateIssueTool);