harbor_list_repos
List all repositories in a Harbor project, showing artifact count and total pulls to identify unused repos. Supports pagination.
Instructions
List repositories in a Harbor project.
Each repository is reported with artifact count and total pull count (useful for spotting unused repos before cleanup).
Pagination: if has_more is True, call again with page + 1.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_name | Yes | Harbor project name. | |
| page | No | Page number (1-based). | |
| page_size | No | Items per page (1-100). |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | ||
| repositories_count | Yes | ||
| page | Yes | ||
| page_size | Yes | ||
| has_more | Yes | ||
| next_page | Yes | ||
| repositories | Yes |
Implementation Reference
- src/harbor_registry_mcp/tools.py:201-246 (handler)The `harbor_list_repos` function — the actual handler that lists repositories in a Harbor project. It calls the Harbor API GET /projects/{project_name}/repositories with pagination, maps each repo to a RepositorySummary (name, artifact_count, pull_count, updated), and returns a RepositoriesListOutput with pagination info.
def harbor_list_repos( project_name: Annotated[str, Field(min_length=1, max_length=255, description="Harbor project name.")], page: Annotated[int, Field(default=1, ge=1, le=1000, description="Page number (1-based).")] = 1, page_size: Annotated[int, Field(default=50, ge=1, le=100, description="Items per page (1-100).")] = 50, ) -> RepositoriesListOutput: """List repositories in a Harbor project. Each repository is reported with artifact count and total pull count (useful for spotting unused repos before cleanup). Pagination: if ``has_more`` is ``True``, call again with ``page + 1``. """ try: client = get_client() raw = ( client.get( f"/projects/{project_name}/repositories", params={"page": page, "page_size": page_size}, ) or [] ) repos: list[RepositorySummary] = [ { "name": r["name"].replace(f"{project_name}/", ""), "artifact_count": int(r.get("artifact_count", 0) or 0), "pull_count": int(r.get("pull_count", 0) or 0), "updated": _short(r.get("update_time")), } for r in raw ] has_more = len(raw) == page_size result: RepositoriesListOutput = { "project": project_name, "repositories_count": len(repos), "page": page, "page_size": page_size, "has_more": has_more, "next_page": page + 1 if has_more else None, "repositories": repos, } md = f"## {project_name} — page {page} ({len(repos)} repos, has_more={has_more})\n\n" + "\n".join( [f"- **{r['name']}** — {r['artifact_count']} artifacts, {r['pull_count']} pulls" for r in repos] ) return output.ok(result, md) # type: ignore[return-value] except Exception as exc: output.fail(exc, f"listing repositories in {project_name}") - src/harbor_registry_mcp/tools.py:190-200 (registration)The `@mcp.tool()` decorator registration for "harbor_list_repos", which registers this function as an MCP tool with read-only, idempotent, non-destructive annotations and structured_output=True.
@mcp.tool( name="harbor_list_repos", annotations={ "title": "List Repositories", "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, "openWorldHint": True, }, structured_output=True, ) - The `RepositorySummary` TypedDict schema — describes the shape of each repository entry returned by the tool.
class RepositorySummary(TypedDict): name: str artifact_count: int pull_count: int updated: str | None - The `RepositoriesListOutput` TypedDict schema — describes the full structured output of the tool (project, count, pagination fields, repository list).
class RepositoriesListOutput(TypedDict): project: str repositories_count: int page: int page_size: int has_more: bool next_page: int | None repositories: list[RepositorySummary] - The `_list_repos` helper function that fetches all repositories across all pages (used internally by other tools like storage report).
def _list_repos(client: Any, project_name: str) -> list[dict[str, Any]]: """Fetch every repository for a project across all pages.""" return client.get_all_pages( f"/projects/{project_name}/repositories", page_size=100, )