Files
AegisGitea-MCP/CLAUDE.md
T

4.1 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, catalog/model.py, cli.py skeleton, audit/security/limits helpers. Planned: catalog generator (B2), executor (B3), server and transports (B4), OAuth (B5), setup command (B6), integration harness and suite (B7, B8), smoke tests (B9), CI (B10), 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)
make validate-audit     # verify audit hash chain
uv run pytest tests/test_config.py::test_defaults -v   # single test

Architecture (target)

  • catalog/: Operation/Parameter model (done), generated tools.json and loader (B2).
  • gitea/ executor: path templating, query/JSON/multipart, Sudo header, pagination, error mapping, limits, masking, result envelope (B3).
  • Server: 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 (B4).
  • Auth: static bearer verifier and OAuth provider with encrypted token store (B5).
  • 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.