docs: rewrite README and docs for the full-access design, generate tool inventory
This commit is contained in:
1 parent
68bd8700dc
commit
7c7cfc05ff
13 files changed
+1693
-1026
No files matched your search
+53
-62
@@ -1,76 +1,67 @@
|
||||
# Troubleshooting
|
||||
|
||||
## "Internal server error (-32603)" from Claude
|
||||
Start with the result of the failing call: errors carry `error.status`, `error.kind` and
|
||||
Gitea's sanitized message, and the audit log has one event per call (see
|
||||
[audit-logging.md](audit-logging.md)).
|
||||
|
||||
**Symptom:** Claude shows `Internal server error` with JSON-RPC error code `-32603` when trying to use Gitea tools.
|
||||
## The server does not start
|
||||
|
||||
**Cause:** In user-token mode, the OAuth token stored by the client may have been issued without Gitea API scopes (e.g. `read:repository`). In service-PAT mode, the call may fail because the authenticated user does not have the required repository permission or the permission probe cannot be completed.
|
||||
| Message or exit | Cause and fix |
|
||||
|---|---|
|
||||
| Exit code 2, "GITEA_TOKEN" required (stdio) | stdio needs `GITEA_TOKEN`. Put it in the client's `env` block or in `.env` in the working directory the client starts the server in. |
|
||||
| Exit code 2, refuses a non-loopback bind | `MCP_HOST` is not loopback and there is no `MCP_BEARER_TOKEN` or complete OAuth setup. Set one of them, or bind `127.0.0.1` behind a reverse proxy. |
|
||||
| Exit code 2, lists OAuth settings | `OAUTH_ENABLED=true` needs `GITEA_OAUTH_CLIENT_ID`, `GITEA_OAUTH_CLIENT_SECRET`, `TOKEN_ENCRYPTION_KEY` and `PUBLIC_BASE_URL`. |
|
||||
| Validation error naming a setting | See the rules in [configuration.md](configuration.md): URLs must be http(s) without credentials, `PUBLIC_BASE_URL` must be https, secrets need 32 characters, `OAUTH_SCOPES` accepts only granular scopes. |
|
||||
| Startup error listing tool names | `DISABLED_TOOLS` contains names that are not registered. Check [tools.md](tools.md). |
|
||||
|
||||
**Fix:**
|
||||
1. In Gitea: Go to **Settings > Applications > Authorized OAuth2 Applications** and revoke the MCP application.
|
||||
2. In Claude: disconnect the MCP server and authenticate again.
|
||||
3. Re-authorize: Use the MCP connector again. It will trigger a fresh OAuth flow. For repository-targeted calls in service-PAT mode, also verify the signed-in Gitea user has read/write access to the target repository.
|
||||
## stdio client shows nothing or breaks
|
||||
|
||||
**Verification:** Check the server logs for `oauth_auth_summary`. A working token shows:
|
||||
```
|
||||
oauth_auth_summary: api_probe=pass login=alice
|
||||
```
|
||||
A scopeless token shows:
|
||||
```
|
||||
oauth_token_lacks_api_scope: status=403 login=alice
|
||||
```
|
||||
stdout carries only JSON-RPC. If a wrapper script prints to stdout before the server starts, the
|
||||
client fails to parse the stream. Logs go to stderr; look at the client's MCP server log.
|
||||
`uvx` needs access to the package index that hosts `aegis-gitea-mcp`, see
|
||||
[packaging.md](packaging.md).
|
||||
|
||||
## "Gitea rejected the API call" (403)
|
||||
## Tool calls fail
|
||||
|
||||
**Symptom:** Tool calls return 403 with a message about re-authorizing.
|
||||
| `kind` | Meaning |
|
||||
|---|---|
|
||||
| `unauthorized` (401) | Gitea rejected the token: wrong, expired or revoked. In OAuth mode the user signs in again. |
|
||||
| `forbidden` (403) | The token or the user lacks the scope or permission. Admin tools return this for non-admins. Widen the token scopes (see "Token scopes" in the [README](../README.md)) or change the user's rights in Gitea. Sudo needs a site-admin token. |
|
||||
| `not_found` (404) | The object does not exist, or Gitea hides it from this identity. Also returned for endpoints the Gitea version lacks. |
|
||||
| `validation_failed` (422), `bad_request` (400) | Gitea rejected the values. The message says which. |
|
||||
| `invalid_argument` | The arguments do not match the tool schema (missing, wrong type, extra property, bad owner or repository name). The message gives the path, not the value. |
|
||||
| `timeout`, `upstream_unreachable` | Gitea did not answer within `REQUEST_TIMEOUT_SECONDS`, or the connection failed. Check `GITEA_URL` from the server's host (DNS, TLS, firewall). |
|
||||
| `redirect` | Gitea answered with a redirect, which is never followed. Use the final URL (for example https) as `GITEA_URL`. |
|
||||
| `payload_too_large` | The response is above `MAX_BINARY_BYTES`. Raise it or fetch a smaller object. |
|
||||
| `secret_blocked` | `SECRET_DETECTION_MODE=block` withheld a result containing secret-like content. Use `mask` if that is acceptable. |
|
||||
| `rate_limited` (429) | Gitea or this server's `RATE_LIMIT_PER_MINUTE` limit. |
|
||||
|
||||
**Cause:** The OAuth token does not have the required API scope in user-token mode, or the per-user repository permission check denied the request in service-PAT mode.
|
||||
A result with a `truncated` object was cut to `MAX_TOOL_RESPONSE_ITEMS` or
|
||||
`MAX_TOOL_RESPONSE_CHARS`. Use `page` and `limit` on paginated tools to walk through it.
|
||||
|
||||
**Fix:** Revoke and re-authorize if the token lacks API scope. If the error mentions repository permission, grant the signed-in Gitea user the required repository access or use a repository they can access.
|
||||
A tool the client cannot see is probably filtered by `TOOLSETS`, `READ_ONLY` or
|
||||
`DISABLED_TOOLS`. Calling a filtered or unknown tool is a protocol error.
|
||||
|
||||
## Claude caches stale tokens
|
||||
## HTTP problems
|
||||
|
||||
**Symptom:** After fixing the OAuth configuration, Claude still sends the old token.
|
||||
- `GET /health` returns 503 `degraded`: the server cannot reach Gitea (the probe is cached for
|
||||
10 seconds). Fix connectivity from the server's host.
|
||||
- 401 on `/mcp`: no or wrong bearer token, and no valid OAuth token. The response has a
|
||||
`WWW-Authenticate` header that points clients to the OAuth metadata.
|
||||
- Request rejected with an invalid Host: the name you used is not allowed. Add it to
|
||||
`ALLOWED_HOSTS` or set `PUBLIC_BASE_URL`.
|
||||
- 429: the client exceeded `RATE_LIMIT_PER_MINUTE`.
|
||||
- Responses arrive in one chunk or time out behind nginx: set `proxy_buffering off;`.
|
||||
|
||||
**Cause:** The client caches access tokens and doesn't automatically re-authenticate when the server configuration changes.
|
||||
## OAuth sign-in
|
||||
|
||||
**Fix:**
|
||||
1. Disconnect the server in the client.
|
||||
2. Start a new conversation and use the integration again - this forces a fresh OAuth flow.
|
||||
|
||||
## How OAuth scopes work with Gitea
|
||||
|
||||
Gitea's OAuth2/OIDC implementation uses **granular scopes** for API access:
|
||||
|
||||
| Scope | Access |
|
||||
|-------|--------|
|
||||
| `read:repository` | Read repositories, issues, PRs, files |
|
||||
| `write:repository` | Create/edit issues, PRs, comments, files |
|
||||
| `openid` | OIDC identity (login, email) |
|
||||
|
||||
When an OAuth application requests authorization, the `scope` parameter in the authorize URL determines what permissions the resulting token has. If only OIDC scopes are requested (e.g. `openid profile email`), the token can establish identity but may not be usable for direct Gitea REST calls. When `GITEA_TOKEN` is configured, the server uses OIDC for identity and checks the user's repository permission before using the service PAT.
|
||||
|
||||
The MCP server's OAuth metadata controls which scopes the client requests. Ensure it includes:
|
||||
```yaml
|
||||
scopes:
|
||||
read:repository: "Read access to Gitea repositories"
|
||||
write:repository: "Write access to Gitea repositories"
|
||||
```
|
||||
|
||||
## Reading the `oauth_auth_summary` log
|
||||
|
||||
Every authenticated request emits a structured log line:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `token_type` | `jwt` or `opaque` |
|
||||
| `scopes_observed` | Scopes extracted from the token/userinfo |
|
||||
| `scopes_effective` | Final scopes after implicit grants |
|
||||
| `api_probe` | `pass`, `fail:403`, `fail:401`, `skip:cached`, `skip:error` |
|
||||
| `login` | Gitea username |
|
||||
|
||||
- `api_probe=pass` — token works for Gitea API calls
|
||||
- `api_probe=fail:403` — token lacks API scopes, request rejected with re-auth guidance
|
||||
- `api_probe=skip:cached` — previous probe passed, cached result used
|
||||
- `api_probe=skip:error` — network error during probe, request allowed to proceed
|
||||
- `repository_permission_denied` in the audit log — the user lacks required read/write permission for a service-PAT call
|
||||
- The client reports that dynamic client registration is unsupported: OAuth is off. Set
|
||||
`OAUTH_ENABLED=true` and the settings that go with it.
|
||||
- Gitea shows a redirect URI error: the OAuth application's redirect URI must be exactly
|
||||
`<PUBLIC_BASE_URL>/oauth/callback`. Re-run `setup --public-base-url ...` or fix it in Gitea.
|
||||
- Signed in, but admin tools return 403: the user is not a site administrator. That is intended.
|
||||
- Users are asked to sign in again after a restart: `TOKEN_ENCRYPTION_KEY` or the `DATA_DIR`
|
||||
volume changed. The key must stay stable and the volume persistent.
|
||||
- After fixing OAuth settings the client still fails: some clients cache tokens. Disconnect the
|
||||
server in the client and connect again, which starts a fresh flow. Users can also revoke the
|
||||
application under Settings, Applications, Authorized OAuth2 Applications in Gitea.
|
||||
Reference in new issue
Block a user