Finding 13: five blocks of near-identical wording were repeated across skills within a plugin — the gitea "resolve owner and repo" step (5 skills), the 404-masks-403 note (6 files), the manual pagination explanation (8 files), the git plugin's main/master force-push refusal (7 files, some with multiple internal restatements), and the bin skills' domain-glossary/ADR paragraph (5 skills). Tightened each instance in place — same meaning, fewer words — rather than extracting to a shared file, which ADR-0014's one-file-per-skill install constraint rules out. Left the three git skills' structured-result JSON shapes alone (coupled to the separate, out-of-scope git-orchestrate merge candidate, finding 19). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
50 lines
2.0 KiB
Markdown
50 lines
2.0 KiB
Markdown
---
|
|
source_keys:
|
|
- gitea-mcp-repo
|
|
- gitea-mcp-slim-go
|
|
---
|
|
|
|
# Reading files, directories and trees
|
|
|
|
All three read calls select what to read with `ref` — a branch name, tag, or commit SHA. On
|
|
`get_repository_tree` the same value goes in `tree_sha` despite the name.
|
|
|
|
## Single file
|
|
|
|
`get_file_contents(owner, repo, ref, path)`.
|
|
|
|
The response carries the file's `sha` at the **top level**, not nested under `content`. That field
|
|
is the write-ready SHA, so capture it whenever a write may follow.
|
|
|
|
Content comes back base64-encoded — decode it — **unless `withLines: true` was passed**, in which
|
|
case `content` is already plain text: a JSON array of `{"line": N, "content": "..."}` objects.
|
|
The response reports `"encoding": "base64"` either way, so that field is wrong under `withLines`
|
|
and decoding on its word yields garbage. Pass `withLines: true` only when you need numbered lines
|
|
to quote specific lines back to the user; omit it for a normal content fetch.
|
|
|
|
## One directory level
|
|
|
|
`get_dir_contents(owner, repo, ref, path)` returns the immediate entries only — name, path, type,
|
|
size. No recursion, no content, no `sha`.
|
|
|
|
## Whole repository tree
|
|
|
|
`get_repository_tree(owner, repo, tree_sha, recursive)`. Set `recursive: true` to walk
|
|
subdirectories in one call.
|
|
|
|
The response sets `truncated: true` when one page doesn't hold every entry — page with
|
|
`page`/`per_page` (defaults `1`/`30`) until a page returns fewer than `per_page`.
|
|
|
|
## Neither listing is a SHA source for a write
|
|
|
|
`get_dir_contents` entries carry no `sha` at all. `get_repository_tree` entries do carry a blob or
|
|
tree hash, but reaching it costs an extra round trip and returns no content. `get_file_contents` is
|
|
the canonical path for a write's SHA: one call returns the decoded content and the write-ready
|
|
`sha` together.
|
|
|
|
## A 404 that is really a 403
|
|
|
|
These reads gate on `write:repository`; an under-scoped token gets 404 instead of 403 so the
|
|
endpoint doesn't leak whether the resource exists. On a path you're confident about, check token
|
|
scope before concluding it doesn't exist.
|