--- 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.