Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gitlab-mcp",
"description": "GitLab MCP server with GraphQL discovery and team activity tools",
"version": "1.15.0",
"version": "1.15.1",
"icon": "assets/logo.svg",
"author": {
"name": "Tim Pearson"
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.15.1] - 2026-05-07

### Fixed

- Write tools (`create_merge_request`, `create_issue`, `update_issue`,
`delete_issue`, `update_merge_request`, `manage_pipeline`, `create_note`,
`delete_note`, `update_note`, `create_broadcast_message`,
`update_broadcast_message`, `delete_broadcast_message`, and the
`requiresWrite` branch of `execute_custom_query`) no longer reject the
request when no per-call `userCredentials` are supplied. They now fall
back to `GITLAB_TOKEN` exactly as documented — a handler-level guard
was short-circuiting the four-step token resolution in `getClient()`,
so writes failed with "User authentication is required…" even when a
full-access env token was configured. Reads were unaffected. Per-call
user credentials and HTTP `Authorization: Bearer` flows continue to
work unchanged. Fixes #32.

## [1.15.0] - 2026-04-27

### Added
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ttpears/gitlab-mcp-server",
"version": "1.15.0",
"version": "1.15.1",
"description": "GitLab MCP Server with GraphQL discovery",
"main": "dist/index.js",
"module": "./src/index.ts",
Expand Down
39 changes: 0 additions & 39 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,6 @@ const createIssueTool: Tool = {
})),
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) {
Expand Down Expand Up @@ -241,9 +238,6 @@ const createMergeRequestTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for creating merge requests. Please provide your GitLab credentials.');
}
const result = await client.createMergeRequest(
input.projectPath,
input.title,
Expand Down Expand Up @@ -279,9 +273,6 @@ const executeCustomQueryTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (input.requiresWrite && !credentials) {
throw new Error('User authentication is required for write operations. Please provide your GitLab credentials.');
}
return await client.query(input.query, input.variables, credentials, input.requiresWrite);
},
};
Expand Down Expand Up @@ -330,9 +321,6 @@ const updateIssueTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required to update issues.');
}
const result = await client.updateIssueComposite(
input.projectPath,
input.iid,
Expand Down Expand Up @@ -363,9 +351,6 @@ const deleteIssueTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for deleting issues.');
}
await client.destroyIssue(input.projectPath.trim(), input.iid.trim(), credentials);
return { projectPath: input.projectPath, iid: input.iid, deleted: true };
},
Expand Down Expand Up @@ -393,9 +378,6 @@ const updateMergeRequestTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required to update merge requests.');
}
const result = await client.updateMergeRequestComposite(
input.projectPath,
input.iid,
Expand Down Expand Up @@ -913,9 +895,6 @@ const managePipelineTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for pipeline management. Please provide your GitLab credentials.');
}
return await client.managePipeline(input.projectPath, input.pipelineIid, input.action, credentials);
},
};
Expand Down Expand Up @@ -1216,9 +1195,6 @@ const createNoteTool: Tool = {
})),
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(', ')}`);
Expand All @@ -1240,9 +1216,6 @@ const deleteNoteTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for deleting notes.');
}
await client.destroyNote(input.noteId.trim(), credentials);
return { noteId: input.noteId, deleted: true };
},
Expand All @@ -1262,9 +1235,6 @@ const updateNoteTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for updating notes.');
}
const result = await client.updateNote(input.noteId.trim(), input.body, credentials);
return result.note;
},
Expand Down Expand Up @@ -1704,9 +1674,6 @@ const createBroadcastMessageTool: Tool = {
inputSchema: withUserAuth(z.object(BroadcastMessageFields)),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for creating broadcast messages.');
}
const { userCredentials, ...body } = input;
return client.createBroadcastMessage(body, credentials);
},
Expand Down Expand Up @@ -1734,9 +1701,6 @@ const updateBroadcastMessageTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for updating broadcast messages.');
}
const { id, userCredentials, ...body } = input;
return client.updateBroadcastMessage(id, body, credentials);
},
Expand All @@ -1754,9 +1718,6 @@ const deleteBroadcastMessageTool: Tool = {
})),
handler: async (input, client, userConfig) => {
const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig;
if (!credentials) {
throw new Error('User authentication is required for deleting broadcast messages.');
}
await client.deleteBroadcastMessage(input.id, credentials);
return { id: input.id, deleted: true };
},
Expand Down
Loading