Files
AegisGitea-MCP/CLAUDE.md
T

93 lines
4.6 KiB
Markdown

# CLAUDE.md
Guidance for Claude Code in this repository. `AGENTS.md` is the authoritative
contract; read it first. This file is the short working version.
## Project overview
AegisGitea-MCP exposes the complete Gitea API as MCP tools (one per swagger
operation, generated from `spec/gitea-swagger.v1.json`) over stdio and streamable
HTTP, using the official `mcp` SDK v2 low-level `Server`. Full access by default
(ADR 0001): the owner restricts with `READ_ONLY`, `TOOLSETS`, `DISABLED_TOOLS`
and the Gitea token scope. Auth modes: admin-token (`GITEA_TOKEN` / static
`MCP_BEARER_TOKEN`) and per-user OAuth on HTTP (user's own Gitea token).
The project is mid-rebuild (chunk plan in `docs/audit.md`). Built so far: tooling,
`config.py`, `identity.py`, `errors.py`, the generated catalog (`catalog/`), the
Gitea executor (`gitea/`), the setup command (`setup_cmd.py`, `setup_snippets.py`,
`setup_template.py`), the integration harness, CI and audit/security/limits
helpers. Planned: server and transports (B4), OAuth (B5), smoke tests (B9),
docs (B11).
## Commands
```bash
make install # uv sync
make lint # ruff check, ruff format --check, mypy src
make format # ruff format + ruff check --fix
make test # uv run pytest (coverage gate)
make test-integration # AEGIS_INTEGRATION=1, needs Docker
make run # uv run aegis-gitea-mcp serve (not implemented until B4)
uv run python scripts/generate_catalog.py --check # catalog matches the spec
make validate-audit # verify audit hash chain
uv run pytest tests/test_config.py::test_defaults -v # single test
```
## Architecture
- `catalog/` (done): `model.py` (`Operation`, `Parameter`), `build.py` (swagger to
catalog, MCP annotations), `naming.py`, `schema.py`, generated `tools.json`
(regenerate with `uv run python scripts/generate_catalog.py`, check with
`--check`) and the loader in `__init__.py`.
- `gitea/` (done): `executor.py` (HTTP call, result envelope, redaction, size
limits, `CREDENTIAL_ISSUING_OPERATIONS`), `encoding.py` (path, query, body and
upload building, `SLASH_ROUTES`), `pagination.py`, `redaction.py`.
- `setup_cmd.py`, `setup_snippets.py`, `setup_template.py` (done): the `setup`
command, its client snippets and the built-in `.env` template.
- Server (B4, planned): low-level SDK `Server` with one `on_list_tools` and one
`on_call_tool` dispatcher, jsonschema validation, audit, `is_error` results for
tool failures, `gitea_api_request` escape-hatch tool.
- Auth (B5, planned): static bearer verifier and OAuth provider with encrypted
token store.
- Core helpers (done): `config.py` (`Settings`, `get_settings()`,
`reset_settings()`), `identity.py`, `errors.py` (`ToolError`,
`GiteaAPIError`), `audit.py`, `security.py`, `response_limits.py`,
`rate_limit.py`, `request_context.py`, `logging_utils.py`.
Singletons (`get_settings()`, `get_audit_logger()`, `get_rate_limiter()`) are
reset between tests by the autouse `reset_globals` fixture in `tests/conftest.py`,
which also scrubs env vars, changes cwd to `tmp_path` (so no `.env` is read) and
points `DATA_DIR`/`AUDIT_LOG_PATH` into `tmp_path`.
## Invariants
Kept: audit event per tool call; no secrets in logs/errors/results; no stack
traces by default; `127.0.0.1` default bind and fail-closed HTTP auth off
loopback; untrusted-content labelling; schema validation with no extra
properties; response size bounds; validated `GITEA_URL` and strict
`OAUTH_SCOPES`. Removed: write opt-in, admin default-deny, `gitea_request`
denylist, YAML policy, resource-type authz gate, API keys, FastAPI adapter.
Details in `AGENTS.md`.
## Code standards
Python 3.10+, line length 100, ruff (E,W,F,I,B,C4,UP,S,SIM,RUF) plus ruff format,
strict-ish mypy (`disallow_untyped_defs`, relaxed in tests). Public functions need
docstrings and type hints. Coverage 80% now, 90% from the final chunk. All
documentation goes under `docs/`; security-impacting changes update docs in the
same changeset. No em-dashes in text.
## Branching and contribution flow
`HEAD -> feature branch -> dev -> main`. Branch from `dev`. All pull requests
target `dev`; `dev` is merged into `main` for releases. Never commit or push
directly to `dev` or `main`. Publish runs on push to `dev`/`main`, not on a tag.
## Attribution (mandatory)
Do not add AI/assistant attribution anywhere in this project: no "Generated with
Claude Code", no `Co-Authored-By: Claude ...` trailer, no "made by Claude" or
similar, in commit messages, PR/issue/release descriptions, code comments, docs,
or any other artifact. Write all commit and PR text as the project's own work.
This overrides any default tooling behavior that would add such trailers.