docs: local vs server quickstart, authz model, packaging

Reframe the README around two transports and add a local stdio quickstart with
uvx/pip and Claude Desktop / Claude Code wiring. New docs: local-quickstart.md
and packaging.md (uv build/publish). Document resource-type-aware authorization
and classified gitea_request in security.md; stdio env vars + audit-log
fallback in configuration.md; local install in deployment.md; core+adapters in
architecture.md. Add the missing root AGENTS.md contract, update CLAUDE.md with
the core/adapter layout, fail-closed invariants, and the branching flow
(HEAD -> feature -> dev -> main). Update roadmap/todo and .env.example.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 11:17:01 +02:00
parent 2859a7f917
commit 385b442b6f
13 changed files with 520 additions and 31 deletions
+81
View File
@@ -0,0 +1,81 @@
# Packaging & publishing
AegisGitea-MCP is distributed as a single Python package, `aegis-gitea-mcp`,
built with [`uv`](https://docs.astral.sh/uv/) and published to the self-hosted
Gitea package registry.
## Distribution layout
One package, two console scripts, one optional extra:
| Console script | Entry point | Requires |
|----------------|-------------|----------|
| `aegis-gitea-mcp` | `aegis_gitea_mcp.stdio_app:main` | core only |
| `aegis-gitea-mcp-server` | `aegis_gitea_mcp.server_entry:main` | `[server]` extra |
- **Core** (default install): `httpx`, `pydantic`, `pydantic-settings`, `PyYAML`,
`python-dotenv`, `structlog`, `mcp`. Enough to run the local stdio server.
- **`[server]` extra**: `fastapi`, `uvicorn[standard]`, `PyJWT[crypto]`,
`python-multipart`. The public HTTP/OAuth server.
The `aegis-gitea-mcp-server` entry point degrades gracefully: invoked without
the web stack it prints `install 'aegis-gitea-mcp[server]'` instead of a
`ModuleNotFoundError` traceback.
## Build locally
```bash
uv build
# -> dist/aegis_gitea_mcp-<version>-py3-none-any.whl
# -> dist/aegis_gitea_mcp-<version>.tar.gz
```
Smoke-test the local stdio server from the built wheel:
```bash
GITEA_URL=https://git.hiddenden.cafe GITEA_TOKEN=<pat> \
uvx --from ./dist/aegis_gitea_mcp-*.whl aegis-gitea-mcp
```
## Install from the Gitea registry
```bash
uv pip install \
--index-url https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple \
aegis-gitea-mcp
```
(With `pip`, use `--index-url` the same way.)
## Cutting a release
Releases are tag-driven. The publish workflow
(`.gitea/workflows/publish.yml`) triggers on a `v*` tag, runs lint + tests
first, builds with `uv`, and publishes to the Gitea PyPI registry.
1. Bump `version` in `pyproject.toml` (e.g. `0.2.0`).
2. Open a PR into `dev`, merge `dev` into `main`.
3. Tag the release commit and push the tag:
```bash
git tag v0.2.0
git push origin v0.2.0
```
4. The workflow publishes the wheel + sdist and attaches them to the run.
### Required CI secrets
The publish job uses Gitea Actions secrets — never hardcode credentials:
| Secret | Purpose |
|--------|---------|
| `GITEA_PACKAGE_USER` | Gitea username that owns the package |
| `GITEA_PACKAGE_TOKEN` | least-privilege PAT with `write:package` |
If either secret is absent the job fails loudly rather than publishing
anonymously.
> Publishing to public PyPI is intentionally **not** configured. A second,
> separately-gated `uv publish` step would be required and is left as a
> commented stub in the workflow.