repo_create tool fails with "Token scope doesn't include write:user for repo creation" when called from claude.ai via the gitea-mcp connector.
Root cause
The Gitea API token used by gitea-mcp (stored as GITEA_MCP_DEFAULT_TOKEN in gitea-mcp-secrets) is missing the write:user scope. The Gitea API requires this scope for POST /api/v1/user/repos.
Current token scopes (gitea-mcp token)
From the Applications page (2026-05-14):
write:issue
write:repository
read:user
Missing: write:user
Fix
Option A — add write:user to existing gitea-mcp token (quickest)
Option B — verify if write:user is actually needed
Check Gitea API docs — POST /api/v1/user/repos may only need write:repository.
The error message may be misleading. Test with a token that has write:repository only.
Recommendation: verify Option B first — if write:repository is sufficient, no token rotation needed.
# Test with current token directly
curl -X POST https://gitea.d-ma.be/api/v1/user/repos \
-H "Authorization: token $DMABE_GITEA_API_TOKEN"\
-H "Content-Type: application/json"\
-d '{"name":"test-scope-check","private":true,"auto_init":false}'| jq .message
# Then delete if created:
curl -X DELETE https://gitea.d-ma.be/api/v1/repos/mathias/test-scope-check \
-H "Authorization: token $DMABE_GITEA_API_TOKEN"
If this works → the gitea-mcp token just needs write:repository added.
If this fails → write:user is genuinely needed.
Impact
Without repo_create working, project_create from claude.ai is broken — the user must manually create repos in Gitea UI before claude.ai can seed files. This defeats the purpose of the automated project initiation flow.
Acceptance criteria
Correct required scopes identified (write:repository or write:user)
gitea-mcp token updated with correct scopes
repo_create callable from claude.ai without error
project_create end-to-end works without manual repo creation
Related
hyperguild #31 (routing-mcp connector — same workflow gap)
gitea-mcp #13 (repo_create original implementation)
## Problem
`repo_create` tool fails with "Token scope doesn't include `write:user` for repo creation" when called from claude.ai via the gitea-mcp connector.
## Root cause
The Gitea API token used by gitea-mcp (stored as `GITEA_MCP_DEFAULT_TOKEN` in `gitea-mcp-secrets`) is missing the `write:user` scope. The Gitea API requires this scope for `POST /api/v1/user/repos`.
## Current token scopes (gitea-mcp token)
From the Applications page (2026-05-14):
- `write:issue`
- `write:repository`
- `read:user`
Missing: `write:user`
## Fix
### Option A — add write:user to existing gitea-mcp token (quickest)
1. `gitea.d-ma.be` → Settings → Applications → find `gitea-mcp` token → Delete
2. Generate new token named `gitea-mcp` with scopes:
- `write:issue`
- `write:repository`
- `read:user`
- `write:user` ← add this
3. Update in 1Password HomeLab: `op item edit GITEA_MCP_DEFAULT_TOKEN --vault HomeLab password=<new-token>`
4. Force ESO sync:
```bash
kubectl annotate externalsecret gitea-mcp-default-token -n gitea-mcp \
force-sync=$(date +%s) --overwrite
kubectl rollout restart deployment/gitea-mcp -n gitea-mcp
```
### Option B — verify if write:user is actually needed
Check Gitea API docs — `POST /api/v1/user/repos` may only need `write:repository`.
The error message may be misleading. Test with a token that has `write:repository` only.
**Recommendation: verify Option B first** — if `write:repository` is sufficient, no token rotation needed.
```bash
# Test with current token directly
curl -X POST https://gitea.d-ma.be/api/v1/user/repos \
-H "Authorization: token $DMABE_GITEA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"test-scope-check","private":true,"auto_init":false}' | jq .message
# Then delete if created:
curl -X DELETE https://gitea.d-ma.be/api/v1/repos/mathias/test-scope-check \
-H "Authorization: token $DMABE_GITEA_API_TOKEN"
```
If this works → the gitea-mcp token just needs `write:repository` added.
If this fails → `write:user` is genuinely needed.
## Impact
Without `repo_create` working, `project_create` from claude.ai is broken — the user must manually create repos in Gitea UI before claude.ai can seed files. This defeats the purpose of the automated project initiation flow.
## Acceptance criteria
- [ ] Correct required scopes identified (write:repository or write:user)
- [ ] gitea-mcp token updated with correct scopes
- [ ] `repo_create` callable from claude.ai without error
- [ ] `project_create` end-to-end works without manual repo creation
## Related
- hyperguild #31 (routing-mcp connector — same workflow gap)
- gitea-mcp #13 (repo_create original implementation)
- local-dev #9, #10 (new-project.sh fixes)
Verified resolved 2026-07-03 — no longer reproduces. Closing.
Tested the live gitea-mcp connector token end-to-end with throwaway repos (created + deleted):
repo_create(mathias/scope-check-tmp, private, auto_init) → success (POST /api/v1/user/repos, the exact path that used to 403 on write:user). No scope error.
Both throwaways deleted afterward. So the gitea-mcp token now carries whatever scope POST /user/repos requires (write:user was added per Option A, or the endpoint only needed write:repository which it already had — either way it works now). No code change needed; MapStatus already surfaces the 401/403 body verbatim, so any future scope gap returns the actionable "Token scope doesn't include X" message.
Separate observation (not this issue): the server-configured default template returned partial_failure: "no placeholders substituted ... verify the scaffold is not left templated" — i.e. the default template repo has no __PROJECT_NAME__/__MODULE_PATH__ placeholders, so the loud-check fires on it. Worth a look at what the deployed default template is (or pass template_name=template-go-agent explicitly). Filing separately if it's a real gap.
Verified resolved 2026-07-03 — no longer reproduces. Closing.
Tested the live gitea-mcp connector token end-to-end with throwaway repos (created + deleted):
- `repo_create(mathias/scope-check-tmp, private, auto_init)` → **success** (`POST /api/v1/user/repos`, the exact path that used to 403 on `write:user`). No scope error.
- `create_project_from_template(mathias/scope-check-tmpl, private)` → **success** (`POST /api/v1/repos/{tmpl}/generate`). Repo created, no scope error.
Both throwaways deleted afterward. So the gitea-mcp token now carries whatever scope `POST /user/repos` requires (`write:user` was added per Option A, or the endpoint only needed `write:repository` which it already had — either way it works now). No code change needed; `MapStatus` already surfaces the 401/403 body verbatim, so any future scope gap returns the actionable "Token scope doesn't include X" message.
**Separate observation (not this issue):** the server-configured *default* template returned `partial_failure: "no placeholders substituted ... verify the scaffold is not left templated"` — i.e. the default template repo has no `__PROJECT_NAME__`/`__MODULE_PATH__` placeholders, so the loud-check fires on it. Worth a look at what the deployed default template is (or pass `template_name=template-go-agent` explicitly). Filing separately if it's a real gap.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
repo_createtool fails with "Token scope doesn't includewrite:userfor repo creation" when called from claude.ai via the gitea-mcp connector.Root cause
The Gitea API token used by gitea-mcp (stored as
GITEA_MCP_DEFAULT_TOKENingitea-mcp-secrets) is missing thewrite:userscope. The Gitea API requires this scope forPOST /api/v1/user/repos.Current token scopes (gitea-mcp token)
From the Applications page (2026-05-14):
write:issuewrite:repositoryread:userMissing:
write:userFix
Option A — add write:user to existing gitea-mcp token (quickest)
gitea.d-ma.be→ Settings → Applications → findgitea-mcptoken → Deletegitea-mcpwith scopes:write:issuewrite:repositoryread:userwrite:user← add thisop item edit GITEA_MCP_DEFAULT_TOKEN --vault HomeLab password=<new-token>Option B — verify if write:user is actually needed
Check Gitea API docs —
POST /api/v1/user/reposmay only needwrite:repository.The error message may be misleading. Test with a token that has
write:repositoryonly.Recommendation: verify Option B first — if
write:repositoryis sufficient, no token rotation needed.If this works → the gitea-mcp token just needs
write:repositoryadded.If this fails →
write:useris genuinely needed.Impact
Without
repo_createworking,project_createfrom claude.ai is broken — the user must manually create repos in Gitea UI before claude.ai can seed files. This defeats the purpose of the automated project initiation flow.Acceptance criteria
repo_createcallable from claude.ai without errorproject_createend-to-end works without manual repo creationRelated
Verified resolved 2026-07-03 — no longer reproduces. Closing.
Tested the live gitea-mcp connector token end-to-end with throwaway repos (created + deleted):
repo_create(mathias/scope-check-tmp, private, auto_init)→ success (POST /api/v1/user/repos, the exact path that used to 403 onwrite:user). No scope error.create_project_from_template(mathias/scope-check-tmpl, private)→ success (POST /api/v1/repos/{tmpl}/generate). Repo created, no scope error.Both throwaways deleted afterward. So the gitea-mcp token now carries whatever scope
POST /user/reposrequires (write:userwas added per Option A, or the endpoint only neededwrite:repositorywhich it already had — either way it works now). No code change needed;MapStatusalready surfaces the 401/403 body verbatim, so any future scope gap returns the actionable "Token scope doesn't include X" message.Separate observation (not this issue): the server-configured default template returned
partial_failure: "no placeholders substituted ... verify the scaffold is not left templated"— i.e. the default template repo has no__PROJECT_NAME__/__MODULE_PATH__placeholders, so the loud-check fires on it. Worth a look at what the deployed default template is (or passtemplate_name=template-go-agentexplicitly). Filing separately if it's a real gap.