Files
AegisGitea-MCP/docs/packaging.md
T
Latte 59d0e43aae docs: fix the claude mcp add form, pin the package index, document known limitations
The --env option swallowed the server name, so the stdio command is reordered. uvx now always
names the project registry because the package name is not registered on public PyPI.
README gains a Known limitations section, the READ_ONLY wording is corrected, packaging.md
warns about --extra-index-url and the Le Chat admin requirement is mentioned.
2026-10-14 18:01:19 +02:00

4.7 KiB

Packaging and publishing

AegisGitea MCP is built with uv (hatchling backend) and published to the self-hosted Gitea package registry on every merge. There are two channels:

Channel Package Published on Version
stable aegis-gitea-mcp push to main X.Y.Z from pyproject.toml
dev aegis-gitea-mcp-dev push to dev X.Y.Z.dev<N>, N is the CI run number

Both build from the same source and install the same import module, aegis_gitea_mcp, and the same console script, aegis-gitea-mcp. They differ only in the distribution name and version. Install one or the other in an environment, not both, because they would collide on the module.

What is in the package

One distribution, one console script:

Console script Entry point
aegis-gitea-mcp aegis_gitea_mcp.cli:main (subcommands serve, setup, version; serve is the default)

Dependencies are the mcp SDK (2.3 or newer, below 3), httpx, pydantic, pydantic-settings, jsonschema, cryptography and uvicorn. There are no extras: both transports and per-user OAuth are in the default install. The generated tool catalog (catalog/tools.json) ships inside the package.

Build locally

uv build
# dist/aegis_gitea_mcp-<version>-py3-none-any.whl
# dist/aegis_gitea_mcp-<version>.tar.gz

Smoke-test the built wheel over stdio:

GITEA_URL=https://git.example.com GITEA_TOKEN=<your-gitea-token> \
  uvx --from ./dist/aegis_gitea_mcp-*.whl aegis-gitea-mcp

Dependencies are pinned in uv.lock; uv sync reproduces the environment.

Install from the Gitea registry

Index URL: https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/

Stable:

# run it without installing into an environment (recommended):
uvx --index https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/ aegis-gitea-mcp

# or install it into an environment:
uv pip install --index https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/ aegis-gitea-mcp

Dev (newest pre-release build, package aegis-gitea-mcp-dev):

uvx --index https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/ --prerelease allow aegis-gitea-mcp-dev

The registry holds only this project's packages and does not proxy PyPI, so it is added with --index and the dependencies (mcp, httpx, ...) still come from PyPI. uv's default index strategy (first-index) takes a package from the first index that has it and never mixes versions across indexes, so with --index the name aegis-gitea-mcp is always taken from this registry, even if somebody registers it on PyPI.

Do not use --extra-index-url with pip. It merges the indexes, and pip picks the highest version from either: whoever publishes aegis-gitea-mcp on PyPI with a higher version number wins (dependency confusion), and the package would run with your Gitea token in its environment. With pip, fetch the wheel from this registry alone, then install it:

pip download --no-deps --index-url https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/ aegis-gitea-mcp -d wheels/
pip install wheels/aegis_gitea_mcp-*.whl

The name is not registered on public PyPI. Publishing there is intentionally not configured, but the owner should reserve both names (aegis-gitea-mcp, aegis-gitea-mcp-dev) on PyPI so nobody else can take them. Until then every install command above must name the index.

To run from a clone instead of a registry: uv run --directory /path/to/AegisGitea-MCP aegis-gitea-mcp serve.

Publishing

Publishing is merge-driven, not tag-driven. .gitea/workflows/publish.yml triggers on a push to dev or main, runs the lint and test gates first, builds with uv build, and publishes with uv publish. The package name and version are patched into pyproject.toml at build time only and never committed.

  • A push to dev publishes aegis-gitea-mcp-dev at X.Y.Z.dev<run number>, unique per run.
  • A push to main publishes aegis-gitea-mcp at the plain X.Y.Z. uv publish --check-url skips files that already exist, so a push that did not bump the version is a clean no-op.

Cutting a stable release

  1. Bump version in pyproject.toml on a branch off dev.
  2. Open a pull request into dev and merge it. That publishes a fresh dev build.
  3. Promote dev to main. The push to main publishes the stable version.

CI secret

Publishing uses the REGISTRY_TOKEN Actions secret, a personal access token with write:package, the same one the image build uses. The token authenticates as its owner, so the job's actor is the username and the token is the password. If the secret is missing the job fails instead of publishing anonymously.

Publishing to public PyPI is intentionally not configured.