create_note
Add comments or notes to GitLab issues and merge requests using Markdown formatting, with options for internal visibility and authentication.
Instructions
Add a comment/note to an issue or merge request (requires user authentication)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectPath | Yes | Full path of the project (e.g., "group/project-name") | |
| noteableType | Yes | Type of item to add a note to | |
| iid | Yes | Issue or merge request IID | |
| body | Yes | Note body (supports Markdown) | |
| internal | No | Whether the note is internal/confidential (only visible to project members) | |
| userCredentials | No | Your GitLab credentials (optional - uses shared token if not provided) |
Implementation Reference
- src/tools.ts:913-942 (handler)Tool definition and handler for 'create_note'. Defines input schema (projectPath, noteableType, iid, body, internal), validates user credentials, and calls the GitLab client's createNote method.
const createNoteTool: Tool = { name: 'create_note', title: 'Create Note', description: 'Add a comment/note to an issue or merge request (requires user authentication)', 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")'), noteableType: z.enum(['issue', 'merge_request']).describe('Type of item to add a note to'), iid: z.string().describe('Issue or merge request IID'), body: z.string().min(1).describe('Note body (supports Markdown)'), internal: z.boolean().default(false).describe('Whether the note is internal/confidential (only visible to project members)'), })), handler: async (input, client, userConfig) => { const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig; if (!credentials) { throw new Error('User authentication is required for creating notes. Please provide your GitLab credentials.'); } const result = await client.createNote(input.projectPath, input.noteableType, input.iid, input.body, input.internal, credentials); if (result.errors && result.errors.length > 0) { throw new Error(`Failed to create note: ${result.errors.join(', ')}`); } return result.note; }, }; - src/gitlab-client.ts:1538-1586 (handler)Core implementation of createNote in GitLabGraphQLClient. Introspects schema, resolves noteable IID to global ID, constructs GraphQL mutation, and executes it to create a note on issues or merge requests.
async createNote( projectPath: string, noteableType: 'issue' | 'merge_request', iid: string, body: string, internal: boolean = false, userConfig?: UserConfig ): Promise<any> { await this.introspectSchema(userConfig); const mutationType = this.schema?.getMutationType(); const fields = mutationType ? mutationType.getFields() : {}; const fieldName = fields['createNote'] ? 'createNote' : null; if (!fieldName) { throw new Error('createNote mutation is not available on this GitLab instance'); } // Resolve the noteable IID to a global ID const noteableId = noteableType === 'issue' ? await this.getIssueId(projectPath, iid, userConfig) : await this.getMergeRequestId(projectPath, iid, userConfig); const mutation = gql` mutation createNote($input: CreateNoteInput!) { createNote(input: $input) { note { id body author { username name } createdAt url internal } errors } } `; const input: any = { noteableId, body, }; if (internal) { input.internal = true; } const result = await this.query(mutation, { input }, userConfig, true); return result.createNote; } - src/tools.ts:924-930 (schema)Input schema definition for create_note tool using Zod validation with user credentials wrapper
inputSchema: withUserAuth(z.object({ projectPath: z.string().describe('Full path of the project (e.g., "group/project-name")'), noteableType: z.enum(['issue', 'merge_request']).describe('Type of item to add a note to'), iid: z.string().describe('Issue or merge request IID'), body: z.string().min(1).describe('Note body (supports Markdown)'), internal: z.boolean().default(false).describe('Whether the note is internal/confidential (only visible to project members)'), })), - src/tools.ts:1317-1349 (registration)Tool registration in module exports. createNoteTool is exported in writeTools array and included in the main tools export for MCP server registration
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, ]; - src/index.ts:83-96 (registration)MCP server tool registration handler. The setupToolHandlers method registers all tools including create_note with the MCP server for listing and execution
private setupToolHandlers(server: Server): void { server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: tools.map(tool => ({ name: tool.name, ...(tool.title && { title: tool.title }), description: tool.description, inputSchema: toJsonSchema(tool.inputSchema), ...(tool.outputSchema && { outputSchema: toJsonSchema(tool.outputSchema) }), ...(tool.annotations && { annotations: tool.annotations }), ...(tool.icon && { icon: tool.icon }), })), }; });