Files
AegisGitea-MCP/docs/troubleshooting.md
T
Latte 59d0e43aae docs: fix the claude mcp add form, pin the package index, document known limitations
The --env option swallowed the server name, so the stdio command is reordered. uvx now always
names the project registry because the package name is not registered on public PyPI.
README gains a Known limitations section, the READ_ONLY wording is corrected, packaging.md
warns about --extra-index-url and the Le Chat admin requirement is mentioned.
2026-10-14 18:01:19 +02:00

86 lines
7.0 KiB
Markdown

# Troubleshooting
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)).
## The server does not start
| 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 an env file passed with `--env-file` (or `AEGIS_ENV_FILE`). A `.env` in the working directory counts only when it is a regular file you own with mode 0600. |
| Warning "ignoring ./.env: ..." | The working directory's `.env` is a symlink, owned by someone else or accessible to group or others, so its settings are not loaded. Run `chmod 600 .env`, or pass `--env-file PATH`. See "Which env file is read" in [configuration.md](configuration.md). |
| Exit code 2, "env file ... does not exist" | The file named by `--env-file` or `AEGIS_ENV_FILE` is missing or not a regular file. |
| 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`. |
| Exit code 2, "cannot decrypt .../oauth-store.json" | `TOKEN_ENCRYPTION_KEY` differs from the key the store was written with (or the file is damaged). The server does not wipe it. Restore the original key, or move `DATA_DIR/oauth-store.json` away to start over (signs every OAuth user out). |
| Exit code 2, "owned by another user" or "writable by group or others" (OAuth) | `DATA_DIR` must belong to the user the server runs as and not be group or world writable. Fix the owner or `chmod 700`. |
| 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). |
## stdio client shows nothing or breaks
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`: pass
`--index https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/`, see
[packaging.md](packaging.md). If you register the server with `claude mcp add`, put `--env`
before `--transport stdio` and the server name, as `setup` prints it.
## Tool calls fail
| `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. |
| `audit_unavailable` | The audit log could not be opened, so the call was refused before it reached Gitea. Fix the permissions of `AUDIT_LOG_PATH` (or `DATA_DIR`) and restart. |
| `rate_limited` (429) | Gitea or this server's `RATE_LIMIT_PER_MINUTE` limit. |
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.
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.
## HTTP problems
- `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 (421): the name you used is not allowed. Add it to
`ALLOWED_HOSTS` or set `PUBLIC_BASE_URL`. With a non-loopback `MCP_HOST` and neither variable
the server prints a warning at startup that says so.
- 429: the client exceeded `RATE_LIMIT_PER_MINUTE`. If every client seems to share one limit,
the proxy address is not in `FORWARDED_ALLOW_IPS`, so all requests look like they come from
the proxy.
- The server exits with code 2 and "cannot open the audit log": the audit file or its directory
is not writable. Fix the permissions, or point `AUDIT_LOG_PATH` or `DATA_DIR` at a writable
location (in Docker, check the volume ownership). The server never runs without an audit log.
- Responses arrive in one chunk or time out behind nginx: set `proxy_buffering off;`.
## OAuth sign-in
- 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: the `DATA_DIR` volume changed or was not
persistent (a changed `TOKEN_ENCRYPTION_KEY` stops startup instead, see above). Keep the key
stable and the volume persistent.
- The sign-in page says the request is invalid or expired: the consent page lives 10 minutes
and a form is single use. Start the sign-in again from the client. Registration or sign-in
refused with "too many": one client address may hold 20 pending sign-ins and register 20
clients per hour.
- 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.