4.6 KiB
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
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, generatedtools.json(regenerate withuv 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): thesetupcommand, its client snippets and the built-in.envtemplate.- Server (B4, planned): low-level SDK
Serverwith oneon_list_toolsand oneon_call_tooldispatcher, jsonschema validation, audit,is_errorresults for tool failures,gitea_api_requestescape-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.