Skip to content

Commit 56c4448

Browse files
committed
ci: add quality gates and contributor guidance
1 parent 9a1786c commit 56c4448

5 files changed

Lines changed: 387 additions & 33 deletions

File tree

.github/workflows/quality.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Quality
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
types: [opened, synchronize, reopened, ready_for_review]
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
17+
18+
jobs:
19+
quality:
20+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
21+
runs-on: ubuntu-24.04
22+
timeout-minutes: 10
23+
steps:
24+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25+
with:
26+
persist-credentials: false
27+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
28+
with:
29+
enable-cache: true
30+
python-version: '3.12'
31+
- run: uv sync --locked --all-groups
32+
- run: uv run ruff check .
33+
- run: uv run ruff format --check .
34+
- run: uv run pytest
35+
- name: Build and install wheel
36+
run: |
37+
uv build --wheel --out-dir dist
38+
uv venv /tmp/vocagateway-mcp-wheel --python 3.12
39+
uv pip install \
40+
--python /tmp/vocagateway-mcp-wheel/bin/python \
41+
dist/*.whl
42+
- name: Smoke-test installed MCP server
43+
run: >-
44+
uv run python scripts/smoke_stdio.py
45+
/tmp/vocagateway-mcp-wheel/bin/vocagateway-mcp
46+
47+
container:
48+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
49+
runs-on: ubuntu-24.04
50+
timeout-minutes: 10
51+
steps:
52+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
53+
with:
54+
persist-credentials: false
55+
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
56+
- name: Build MCP image
57+
run: |
58+
docker buildx build \
59+
--tag vocagateway-mcp:test \
60+
--cache-from type=gha,scope=vocagateway-mcp \
61+
--cache-to type=gha,mode=max,scope=vocagateway-mcp \
62+
--output type=cacheonly \
63+
.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
.venv/
22
.pytest_cache/
3+
.ruff_cache/
34
__pycache__/
45
*.py[cod]
56
*.profraw
7+
dist/

AGENTS.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# AGENTS.md
2+
3+
Instructions for coding agents in this repository.
4+
5+
`vocagateway-mcp` is a thin MCP client for a user-operated
6+
[VocaGateway](https://github.com/VocaHQ/vocagateway). It does not perform speech
7+
inference itself. The current milestone is a local stdio server that reports
8+
gateway status, lists models, and sends a completed local audio file to the
9+
explicitly configured gateway. There is no Voca-hosted relay, account, or cloud
10+
transcription service.
11+
12+
## Critical: git worktrees for every branch and PR
13+
14+
Never create a branch, commit, or open a pull request in the primary checkout.
15+
Use a linked git worktree so the primary checkout stays on `main` and clean.
16+
17+
```bash
18+
git fetch origin
19+
git worktree add /tmp/vocagateway-mcp-<task> -b <type>/<short-name> origin/main
20+
21+
# Edit, test, commit, push, and open the PR inside that worktree.
22+
23+
git worktree remove /tmp/vocagateway-mcp-<task>
24+
git worktree prune
25+
```
26+
27+
Rules:
28+
29+
- One worktree per branch and one logical change per PR.
30+
- Put worktrees outside the primary checkout.
31+
- Never commit or push directly to `main`.
32+
- Never merge a PR; wait for maintainer review.
33+
- Clean up the worktree after the branch is published.
34+
35+
## Layout
36+
37+
| Path | Role |
38+
| --- | --- |
39+
| `src/vocagateway_mcp/client.py` | Configuration, HTTP client, destination confirmation, safe errors |
40+
| `src/vocagateway_mcp/server.py` | FastMCP tools and stdio entry point |
41+
| `tests/` | Unit tests using `httpx.MockTransport`; no live gateway required |
42+
| `scripts/inspect-local.sh` | Local MCP Inspector launcher using the gateway token file |
43+
| `scripts/smoke_stdio.py` | Installed-wheel MCP initialize and tool-list smoke test |
44+
| `Dockerfile` | Stdio container image |
45+
| `.github/workflows/quality.yml` | Python/package/protocol and container CI gates |
46+
47+
## Setup and commands
48+
49+
Python 3.12+ and `uv` are required. `uv.lock` is authoritative and must be
50+
committed whenever dependencies change.
51+
52+
```bash
53+
uv sync --locked --all-groups
54+
uv run ruff check .
55+
uv run ruff format --check .
56+
uv run pytest
57+
58+
uv build --wheel
59+
uv run python scripts/smoke_stdio.py .venv/bin/vocagateway-mcp
60+
docker build --tag vocagateway-mcp:test .
61+
```
62+
63+
Use `uv run ruff format .` and `uv run ruff check --fix .` for mechanical fixes.
64+
Run `git diff --check` before committing.
65+
66+
## Architecture and API contract
67+
68+
- Keep gateway-independent logic in `GatewayClient`; MCP tools should be thin
69+
adapters so a future Streamable HTTP transport can reuse the same client.
70+
- Stdio is the only supported MCP transport in the current milestone.
71+
- `get_gateway_status` uses public gateway health endpoints.
72+
- `list_models` is read-only but uses the configured gateway bearer token.
73+
- `transcribe_file` uses `POST /v1/audio/transcriptions` and must require the
74+
caller to confirm the normalized gateway URL before the file is opened.
75+
- Do not add streaming transcription, token administration, model mutations,
76+
arbitrary URL ingestion, or a hosted Voca relay without an explicit product
77+
decision.
78+
- Coordinate changes to gateway paths or response shapes with
79+
`VocaHQ/vocagateway`; do not silently invent compatibility behavior.
80+
81+
## Privacy and security
82+
83+
Never commit or log:
84+
85+
- Bearer tokens or token files
86+
- Audio recordings or transcripts, including test fixtures
87+
- Personal gateway URLs, LAN addresses, or tailnet hostnames
88+
- `.env` files, diagnostics containing secrets, or local application data
89+
90+
Tests must use generated bytes, synthetic metadata, and reserved example hosts.
91+
Do not echo gateway response bodies in errors because they may contain secrets
92+
or transcripts. Do not weaken destination confirmation, bearer authentication,
93+
timeouts, upload controls, or error redaction without explicit review.
94+
95+
Local file access must remain bounded to the path the caller supplied. Hosted
96+
transport work must define a remote-safe audio input contract; a path on the MCP
97+
server is not the remote user's local file.
98+
99+
## Python conventions and tests
100+
101+
- Use `from __future__ import annotations`.
102+
- Ruff targets Python 3.12 with line length 100.
103+
- Prefer explicit types, small async methods, specific exceptions, and early
104+
validation before file or network access.
105+
- Tests live in `tests/test_*.py`; use `pytest` and `httpx.MockTransport`.
106+
- Unit tests must not require VocaGateway, VocaMac, a speech model, Docker, or
107+
network access.
108+
- Every new tool needs schema/registration coverage and success, validation,
109+
authentication, and secret-redaction tests where applicable.
110+
- Keep stdout reserved for MCP JSON-RPC; diagnostics belong on stderr.
111+
112+
## CI, commits, and pull requests
113+
114+
`quality.yml` runs on pushes to `main`, non-draft PRs, and manual dispatch. It
115+
checks the lockfile, Ruff, pytest, a clean wheel install, an MCP stdio handshake,
116+
and the Docker build.
117+
118+
Use Conventional Commits: `feat`, `fix`, `docs`, `test`, `ci`, `refactor`,
119+
`build`, or `chore`. PR descriptions should include:
120+
121+
- Summary and rationale
122+
- Exact verification commands and results
123+
- Privacy/security impact
124+
- Any live-gateway or container testing performed
125+
126+
Update this file when commands, layout, supported transports, or agent rules
127+
change.

0 commit comments

Comments
 (0)