6.0 KiB
Project context
Identity
- Name: gitea-mcp
- Owner: Mathias
- Client: personal
- Repo: https://gitea.d-ma.be/mathias/gitea-mcp
- Status: active
Stack
- Primary language: Go
- UI layer: HTMX + Templ (when applicable)
- Fallback languages: Python, TypeScript (justify in PR if used)
- Build: Task (taskfile.dev), not Make
- Containers: Docker (compose for dev, k3s for deploy)
- Target infra: koala (GPU workloads), iguana (services), flamingo (edge)
Conventions
Code style
- Go: follow
golines,gofumpt,golangci-lintwith project config - Tests: table-driven, in
_test.gonext to source,testifyfor assertions - Errors: wrap with
fmt.Errorf("operation: %w", err), no naked returns - Naming: stdlib conventions, no stuttering (
http.Clientnothttp.HTTPClient)
Architecture preferences
- Prefer standard library over frameworks (net/http over gin/echo)
- Dependency injection via constructor functions, not containers
- Configuration via environment variables, parsed at startup into a typed struct
- Structured logging via
slog
Git
- Conventional commits:
feat:,fix:,chore:,docs:,refactor: - Branch naming:
feat/short-description,fix/short-description - PRs: one concern per PR, description explains why not what
Security
- No secrets in code, ever — use env vars or SOPS-encrypted files
- Client data never leaves local network unless explicitly cleared
- Dependencies: audit with
govulncheckbefore adding
Knowledge base access
This project can query the shared knowledge base via MCP or HTTP:
- MCP endpoint:
mcp://localhost:3100/knowledge - HTTP fallback:
http://localhost:3100/api/v1/search - Scoping: queries are filtered to collection
personal+public
Behavior rules
These rules apply to every task in this project, regardless of harness.
- No assumptions. Don't hide confusion — surface it. Surface tradeoffs explicitly. Think before coding; if the problem is unclear, ask or state assumptions before acting.
- Minimum viable code. Solve with the smallest change that works. Nothing speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
- Surgical changes. Touch only what the task requires. Leave unrelated code, files, and formatting alone. Diffs should be small and reviewable.
- Goal-driven execution. Define clear success criteria up front for every task. Loop — implement, verify, refine — until those criteria are met. Don't claim completion without evidence (tests pass, command output, observed behavior).
Agent instructions
When acting as a coding agent on this project:
- Read this file and all
SKILL.mdfiles in.skills/before starting work - Run
task checkbefore committing (lint + test + vet) - If unsure about a convention, check
DECISIONS.mdor ask - Never modify files outside the project root without explicit permission
- When adding a dependency, explain why in the commit message
- For client projects: never send code or context to cloud APIs — use local models via LiteLLM
Current sprint — gitea-mcp v0.2 (2026-05-14)
Context
This sprint implements new MCP tools needed for hyperguild new-project —
the automated project creation flow triggered from claude.ai. See brain knowledge
nodes adr-new-project-gitea-first-github-mirror and roadmap-github-ingestion-pipeline
for full background.
Issues to implement (priority order)
Batch 1 — blockers (do first, one PR: feat/repo-crud)
| Issue | Tool | Gitea API |
|---|---|---|
| #13 | repo_create |
POST /api/v1/user/repos or /api/v1/orgs/{org}/repos |
| #16 | repo_mirror_push (add/list/delete) |
POST/GET/DELETE /api/v1/repos/{owner}/{repo}/push_mirrors |
| #12 | repo_update |
PATCH /api/v1/repos/{owner}/{repo} |
Batch 2 — quality of life (second PR: feat/repo-ux)
| Issue | Tool | Gitea API |
|---|---|---|
| #15 | file_read dir-path fix |
existing endpoint, detect array vs object response |
| #14 | repo_tree |
GET /api/v1/repos/{owner}/{repo}/git/trees/{sha}?recursive=true |
| #18 | repo_topics_update |
PUT /api/v1/repos/{owner}/{repo}/topics |
Batch 3 — can wait
| Issue | Tool | Note |
|---|---|---|
| #11 | repo_delete |
HIGH risk — needs confirm param == repo name |
| #17 | release_create |
POST /api/v1/repos/{owner}/{repo}/releases |
How to add a tool (pattern)
Every tool = 4 files following internal/tools/repo_get.go exactly:
internal/gitea/<domain>.go— API client method (use PostJSON/PatchJSON/DeleteJSON)internal/tools/repo_<name>.go— tool handler with Descriptor() + Call()internal/tools/repo_<name>_test.go— table-driven tests with httptest.NewServer- Registration in main — find where
NewRepoGetis registered, add new tool same place
Key rules:
- Always call
t.a.Check(args.Owner)before any API call (allowlist guard) - Use
textOK(result)for success output - For
repo_mirror_push: NEVER log or returnremote_passwordin any output - For
repo_updatewithprivate: falseandrepo_delete: requireconfirmparam == repo name
Token permissions needed
New tools require these additional Gitea token scopes:
write:repository— repo_create, repo_update, repo_mirror_push, repo_topics_update, release_createdelete_repo— repo_delete
Check current token: curl -H "Authorization: token $GITEA_TOKEN" https://gitea.d-ma.be/api/v1/user
If scopes are missing, update token in Gitea settings before running tests.
Definition of done
task checkpasses (all tools, all batches)- Each new tool manually callable via
claude mcp call - PR #1 (batch 1) merged before starting batch 2
- Issue #19 (mirror flow e2e test) verified manually after batch 1 is deployed