Skip to content

Add pagination support to list_tags tool with sorting options #46

@JAORMX

Description

@JAORMX

Problem

The list_tags tool currently returns all tags from a repository in a single response with no pagination or limits. This can cause:

  • Memory issues for repositories with thousands of tags
  • Poor performance with large result sets
  • Poor user experience - no way to incrementally fetch results or get the most relevant tags first

MCP Best Practices

According to the MCP specification, while the built-in list operations (resources/list, prompts/list, tools/list) use cursor-based pagination, custom tools should implement their own pagination strategy appropriate for their use case.

For list operations in tools, best practices recommend:

  • Setting reasonable defaults to avoid overwhelming responses
  • Providing cursor or page-based navigation for large result sets
  • Being transparent about pagination behavior in tool descriptions

Proposed Solution

Add pagination support to the list_tags tool with the following parameters:

New Parameters

  1. limit (integer, optional)

    • Default: 100
    • Maximum number of tags to return per request
    • Should align with registry API capabilities
  2. cursor (string, optional)

    • Opaque pagination cursor for fetching the next page of results
    • Returned in the response as nextCursor when more results are available
    • Should be treated as an opaque token by clients (following MCP best practices)
  3. sort (string, optional, enum)

    • Default: name (alphabetical)
    • Options:
      • name: Alphabetical order (A-Z)
      • name_desc: Reverse alphabetical order (Z-A)
      • created: Oldest first (if registry supports it)
      • created_desc: Newest first (if registry supports it)
    • Allows users to get most relevant results faster

Response Format

The tool should return:

{
  "tags": ["tag1", "tag2", "..."],
  "nextCursor": "opaque-cursor-string-or-null",
  "total": 1234  // optional: if registry provides it
}

Implementation Notes

The go-containerregistry library already supports pagination through:

  1. Low-level pagination via fetcher.listPage() in pkg/v1/remote/list.go:

    • Supports pageSize parameter (n query param in registry API)
    • Returns Next link for subsequent pages via Link header
    • The Lister type provides HasNext() and Next(ctx) methods
  2. Current implementation via remote.List():

    • Returns all tags by automatically handling pagination internally
    • We need to expose the underlying pagination capabilities to the tool

Implementation Strategy

  1. Use the fetcher.listPage() method or create a similar paginated approach
  2. Store the pagination state (next URL) in an opaque cursor
  3. For sorting:
    • name sorting is default (registry provides alphabetical order)
    • For created sorting, we may need to fetch tag metadata unless registry provides it
    • Client-side sorting fallback if registry doesn't support the requested order

Backward Compatibility

  • All new parameters are optional with sensible defaults
  • Existing tool calls without pagination parameters will continue to work
  • Default limit of 100 prevents accidentally fetching thousands of tags

Example Usage

// Initial request
{
  "tool": "list_tags",
  "arguments": {
    "repository": "docker.io/library/alpine",
    "limit": 50,
    "sort": "name"
  }
}

// Response
{
  "tags": ["2.6", "2.7", ..., "3.19"],
  "nextCursor": "eyJuZXh0IjoiaHR0cHM6Ly9yZWdpc3RyeS0xLmRvY2tlci5pby92Mi9saWJyYXJ5L2FscGluZS90YWdzL2xpc3Q/bj01MCZsYXN0PTMuMTkifQ=="
}

// Fetch next page
{
  "tool": "list_tags",
  "arguments": {
    "repository": "docker.io/library/alpine",
    "cursor": "eyJuZXh0IjoiaHR0cHM6Ly9yZWdpc3RyeS0xLmRvY2tlci5pby92Mi9saWJyYXJ5L2FscGluZS90YWdzL2xpc3Q/bj01MCZsYXN0PTMuMTkifQ=="
  }
}

Additional Considerations

  • Update tool description to document pagination behavior
  • Consider adding integration tests with repositories that have many tags
  • Document the cursor format in code comments (even though it's opaque to clients)
  • Handle registry-specific pagination differences gracefully

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions