93 lines
4.6 KiB
Markdown
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.
|