# GitLab MCP 401 on one action while the same token works elsewhere

**TL;DR:** GitLab answers 401 for a valid token that lacks permission on that action, not just for bad tokens. Test the same token on a simple call; if it works there, the 401 is a permission refusal. Grant the missing permission (or the api scope) instead of regenerating the token.

## The error

```
401 Unauthorized on specific GitLab MCP actions (e.g. approving a merge request you opened) while the same token succeeds on other calls
```

## Fix it

1. Run a simple call with the same token, like listing projects.
   Expected: It succeeds, proving the token is valid.
2. Retry the failing action.
   Expected: It 401s again, confirming a per-action refusal.
3. Check the project settings for the action: approval rules, protected branches, author-cannot-approve.
   Expected: You find the policy blocking it.
4. Adjust the policy or use a token with the needed role.
   Expected: The action succeeds.

## When this applies

A GitLab MCP token works for reads but returns 401 on specific write or approval actions.

## When this does NOT apply

If the token 401s on everything, it is invalid or expired; regenerate it instead.

## Tool compatibility

jmrplens/gitlab-mcp-server, GitLab REST API

## Also seen as

- GitLab 401 approve merge request MCP
- GitLab valid token 401 permission
- GitLab unauthorized! valid credential

## Why it happens

GitLab's API helper answers 401 (not 403) when a valid credential lacks permission for the route, covering merges, approvals, mirrors, and token management. The status alone cannot distinguish this from bad auth, so the same-token test is the discriminator.

## Edge cases

- Instances that prevent approval by the author are the most common trigger.
- The REST body sometimes carries the invalid_token code only for truly dead tokens.
- Project access tokens inherit the bot user's role; check that role first.