create_issue
Create new issues in GitLab projects to track tasks, bugs, or feature requests. Requires write permissions and project path.
Instructions
Create a new issue in a GitLab project (requires user authentication with write permissions)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectPath | Yes | Full path of the project (e.g., "group/project-name") | |
| title | Yes | Title of the issue | |
| description | No | Description of the issue | |
| userCredentials | No | Your GitLab credentials (optional - uses shared token if not provided) |
Implementation Reference
- src/tools.ts:170-198 (registration)Tool definition and registration for create_issue - defines the tool name, description, input schema (with user credentials), and the handler that executes when the tool is called
const createIssueTool: Tool = { name: 'create_issue', title: 'Create Issue', description: 'Create a new issue in a GitLab project (requires user authentication with write permissions)', requiresAuth: true, requiresWrite: true, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, }, inputSchema: withUserAuth(z.object({ projectPath: z.string().describe('Full path of the project (e.g., "group/project-name")'), title: z.string().min(1).describe('Title of the issue'), description: z.string().optional().describe('Description of the issue'), })), handler: async (input, client, userConfig) => { const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig; if (!credentials) { throw new Error('User authentication is required for creating issues. Please provide your GitLab credentials.'); } const result = await client.createIssue(input.projectPath, input.title, input.description, credentials); const payload = result.createIssue; if (payload.errors && payload.errors.length > 0) { throw new Error(`Failed to create issue: ${payload.errors.join(', ')}`); } return payload.issue; }, }; - src/tools.ts:186-197 (handler)Tool handler function that processes create_issue requests - validates user credentials, calls the client's createIssue method, and returns the created issue or throws an error
handler: async (input, client, userConfig) => { const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig; if (!credentials) { throw new Error('User authentication is required for creating issues. Please provide your GitLab credentials.'); } const result = await client.createIssue(input.projectPath, input.title, input.description, credentials); const payload = result.createIssue; if (payload.errors && payload.errors.length > 0) { throw new Error(`Failed to create issue: ${payload.errors.join(', ')}`); } return payload.issue; }, - src/gitlab-client.ts:425-469 (handler)Client method that implements the actual create_issue logic using GraphQL mutation - introspects schema to determine the correct mutation field name and input type, builds the mutation query, and executes it
async createIssue(projectPath: string, title: string, description?: string, userConfig?: UserConfig): Promise<any> { await this.introspectSchema(userConfig); const mutationType = this.schema?.getMutationType(); const fields = mutationType ? mutationType.getFields() : {}; const fieldName = fields['createIssue'] ? 'createIssue' : (fields['issueCreate'] ? 'issueCreate' : null); if (!fieldName) { throw new Error('Neither createIssue nor issueCreate mutation is available on this GitLab instance'); } const hasCreateInput = !!this.schema.getType('CreateIssueInput'); const hasLegacyInput = !!this.schema.getType('IssueCreateInput'); const inputType = hasCreateInput ? 'CreateIssueInput' : (hasLegacyInput ? 'IssueCreateInput' : null); if (!inputType) { throw new Error('Neither CreateIssueInput nor IssueCreateInput input type is available on this GitLab instance'); } const mutation = gql` mutation createIssue($input: ${inputType}!) { ${fieldName}(input: $input) { issue { id iid title description webUrl state createdAt } errors } } `; const input = { projectPath, title, description, }; const result = await this.query(mutation, { input }, userConfig, true); // Normalize payload to { createIssue: ... } const payload = (result as any)[fieldName]; return { createIssue: payload }; } - src/tools.ts:181-185 (schema)Input schema definition for create_issue tool using Zod - validates projectPath (required), title (required, min 1 char), and description (optional), plus optional userCredentials
inputSchema: withUserAuth(z.object({ projectPath: z.string().describe('Full path of the project (e.g., "group/project-name")'), title: z.string().min(1).describe('Title of the issue'), description: z.string().optional().describe('Description of the issue'), })), - src/tools.ts:1317-1349 (registration)Export of the createIssueTool as part of writeTools array and main tools export - makes it available for registration with the MCP server
export const writeTools: Tool[] = [ createIssueTool, createMergeRequestTool, createNoteTool, managePipelineTool, ]; export const searchTools: Tool[] = [ globalSearchTool, searchProjectsTool, searchIssuesTool, searchMergeRequestsTool, getUserIssuesTool, getUserMergeRequestsTool, searchUsersTool, searchGroupsTool, searchLabelsTool, browseRepositoryTool, getFileContentTool, listGroupMembersTool, ]; export const tools: Tool[] = [ ...readOnlyTools, ...userAuthTools, ...writeTools, updateIssueTool, updateMergeRequestTool, resolvePathTool, getGroupProjectsTool, getTypeFieldsTool, ...searchTools, ];