Feature request: list_repo_contents and get_repo_tree MCP tools #115
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/OpenSpec
Kind/Security
Kind/Testing
Priority/Critical
Priority/High
Priority/Low
Priority/Medium
RFC - Request For Comments
Reviewed/Confirmed
Reviewed/Duplicate
Reviewed/Invalid
Reviewed/Won't Fix
Status/Abandoned
Status/Blocked
Status/Need More Info
hermes-attempted
hermes-needs-clarification
hermes-ready
hermes-review
hermes-wip
human-required
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
agentic-forges/forgejo-mcp#115
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The
operation/repo/domain exposes tools for file CRUD, branch management, and commit listing, but there is no way to discover what files or directories exist in a repository. Two complementary tools would close this gap:list_repo_contents— list directory entries at a given path using the SDK'sListContentsmethod (/repos/{owner}/{repo}/contents/{path})get_repo_tree— retrieve a full Git tree for a ref using the SDK'sGetTreesmethod (/repos/{owner}/{repo}/git/trees/{ref})Without these, an MCP client that wants to navigate a repository must call
get_file_contentwith guessed paths, which is awkward in an agentic context.Proposed tools
Tool 1:
list_repo_contentslist_repo_contentsis called withowner,repo,ref, andpath(empty string for root)→ THEN returns the array of
ContentsResponseentries at that path (name, path, typefile/dir/symlink/submodule, sha, size)Tool 2:
get_repo_treeWHEN
get_repo_treeis called withowner,repo,ref, andrecursive=false(default)→ THEN returns a
GitTreeResponsewith the top-level entries for that refWHEN
get_repo_treeis called withrecursive=true→ THEN returns a
GitTreeResponsewith all entries in the full treeBoth tools follow the existing registration pattern (
mcp.NewTool+mcp.WithString/mcp.WithNumber/mcp.WithBoolean, handler returnsto.TextResult(result)).Breaking change note
None. This is a pure addition — two new tools, no changes to existing tools or handlers.
Open design point: pagination in
list_repo_contentsThe current SDK signature is:
It accepts no pagination options. The proposed implementation includes
pageandlimitparameters in the tool definition for consistency with other list-tools (list_branches,list_repo_commits, etc.), but does not forward them to the SDK call.Two acceptable resolutions — happy to defer to your preference:
(a) Accept the inconsistency and document it: keep
page/limitin the tool definition as a forward-compatible placeholder until the SDK supports pagination on this endpoint.(b) Drop
page/limitfrom the tool definition entirely: lean interface, no phantom parameters, revisit when the SDK adds support.get_repo_treedoes not have this issue —GetTreesOptionsalready embedsListOptions{Page, PageSize}.Working implementation
A working implementation is available at
BrilliantKahn/forgejo-mcp, branchfeat/repo-tree-listing.Changes are confined to three files:
operation/repo/contents.go(new) — both tool definitions and handlersoperation/repo/repo.go— registration of both toolsoperation/repo/contents_test.go(new) — white-boxhttptest-mock tests for both success pathsThe branch is based on upstream main HEAD
25ecabdd(v2.19.0, 2026-05-02).make buildandgo test ./...pass.This is a request for feedback on the approach and the pagination design point above — not a PR announcement. I want to confirm the parameter shape and your preference on option (a) vs (b) before opening a PR.
SDK rationale
list_repo_contentsusesListContentsrather thanGetContentsbecause the tool's purpose is directory listing;GetContentsreturns a singleContentsResponseand errors on directories.get_repo_treeusesGetTrees(SDK method) directly. Two tools rather than one with arecursiveflag: the two SDK methods return structurally different types ([]*ContentsResponsevs*GitTreeResponse), and merging them would require transformation logic that conflicts with the 1-to-1 SDK-wrapping pattern the repo uses.Thanks again — and again, the production-tested branch up front makes this easy.
Two tools rather than one with a
recursiveflag is the right call. Different SDK return types, different shapes, no value in pretending otherwise. Matches the 1-to-1 wrapping we have everywhere else.On the pagination question: option (b). Drop
page/limitfromlist_repo_contentsuntil the SDK actually supports them. Every other paginated tool inoperation/repo/(list_branches,list_repo_commits,list_my_repos) wires those params straight into a realListOptions{Page, PageSize}. Phantom params would break that contract and lie to the MCP schema — caller seespage=2accepted, gets page 1 back, no error. That's a worse failure mode than not having pagination at all. When the SDK adds support, we add the params then. No forward-compat placeholder.get_repo_treekeepspage/limitsinceGetTreesOptionsactually plumbs them through. Good.No breaking change, pure addition — minor bump, v2.20.0 (or rolled into the same release as #114, depending on which lands first).
Open the PR against
main.feat:commit, squash. Tool descriptions should be precise about whatpath=""means forlist_repo_contents(root) and whatrecursivedoes onget_repo_tree, so the LLM picks the right one without trial and error.