Skip to main content
Glama

list_repo_issues

Retrieve and display issues from a specified repository on the Tangled git collaboration platform. Use this tool to view repository issues by providing the repository identifier and optional limit parameter.

Instructions

list issues for a repository

Args: repo: repository identifier in 'owner/repo' format limit: maximum number of issues to return (1-100)

Returns: ListIssuesResult with list of issues

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repoYesrepository identifier in 'owner/repo' format (e.g., 'zzstoatzz/tangled-mcp')
limitNomaximum number of issues to return

Implementation Reference

  • MCP tool handler: resolves repo identifier, calls core _tangled.list_repo_issues, returns ListIssuesResult instance.
    @tangled_mcp.tool def list_repo_issues( repo: Annotated[ str, Field( description="repository identifier in 'owner/repo' format (e.g., 'zzstoatzz/tangled-mcp')" ), ], limit: Annotated[ int, Field(ge=1, le=100, description="maximum number of issues to return") ] = 20, ) -> ListIssuesResult: """list issues for a repository Args: repo: repository identifier in 'owner/repo' format limit: maximum number of issues to return (1-100) Returns: ListIssuesResult with list of issues """ # resolve owner/repo to (knot, did/repo) _, repo_id = _tangled.resolve_repo_identifier(repo) # list_repo_issues doesn't need knot (queries atproto records, not XRPC) response = _tangled.list_repo_issues(repo_id, limit, cursor=None) return ListIssuesResult.from_api_response(response)
  • Pydantic model ListIssuesResult for output schema, with from_api_response classmethod to parse core API response.
    class ListIssuesResult(BaseModel): """result of listing issues""" issues: list[IssueInfo] @classmethod def from_api_response(cls, response: dict[str, Any]) -> "ListIssuesResult": """construct from raw API response Args: response: raw response from tangled API with structure: { "issues": [ { "uri": "at://...", "cid": "bafyrei...", "issueId": 1, "title": "...", "body": "...", "createdAt": "..." }, ... ] } Returns: ListIssuesResult with parsed issues """ issues = [IssueInfo(**issue_data) for issue_data in response.get("issues", [])] return cls(issues=issues)
  • Core helper function: queries atproto repo records for issues and label ops, filters by repo, assembles issue data with labels.
    def list_repo_issues( repo_id: str, limit: int = 50, cursor: str | None = None ) -> dict[str, Any]: """list issues for a repository Args: repo_id: repository identifier in "did/repo" format limit: maximum number of issues to return cursor: pagination cursor Returns: dict containing issues and optional cursor """ client = _get_authenticated_client() if not client.me: raise RuntimeError("client not authenticated") # parse repo_id to get owner_did and repo_name if "/" not in repo_id: raise ValueError(f"invalid repo_id format: {repo_id}") owner_did, repo_name = repo_id.split("/", 1) # get the repo AT-URI by querying the repo collection records = client.com.atproto.repo.list_records( models.ComAtprotoRepoListRecords.Params( repo=owner_did, collection="sh.tangled.repo", limit=100, ) ) repo_at_uri = None for record in records.records: if ( name := getattr(record.value, "name", None) ) is not None and name == repo_name: repo_at_uri = record.uri break if not repo_at_uri: raise ValueError(f"repo not found: {repo_id}") # list records from the issue collection response = client.com.atproto.repo.list_records( models.ComAtprotoRepoListRecords.Params( repo=client.me.did, collection="sh.tangled.repo.issue", limit=limit, cursor=cursor, ) ) # filter issues by repo issues = [] issue_uris = [] for record in response.records: if ( repo := getattr(record.value, "repo", None) ) is not None and repo == repo_at_uri: issue_uris.append(record.uri) issues.append( { "uri": record.uri, "cid": record.cid, "issueId": getattr(record.value, "issueId", 0), "title": getattr(record.value, "title", ""), "body": getattr(record.value, "body", None), "createdAt": getattr(record.value, "createdAt", ""), "labels": [], # will be populated below } ) # fetch label ops and correlate with issues if issue_uris: label_ops = client.com.atproto.repo.list_records( models.ComAtprotoRepoListRecords.Params( repo=client.me.did, collection="sh.tangled.label.op", limit=100, ) ) # build map of issue_uri -> current label URIs issue_labels_map: dict[str, set[str]] = {uri: set() for uri in issue_uris} for op_record in label_ops.records: if ( hasattr(op_record.value, "subject") and op_record.value.subject in issue_labels_map ): subject_uri = op_record.value.subject if hasattr(op_record.value, "add"): for operand in op_record.value.add: if hasattr(operand, "key"): issue_labels_map[subject_uri].add(operand.key) if hasattr(op_record.value, "delete"): for operand in op_record.value.delete: if hasattr(operand, "key"): issue_labels_map[subject_uri].discard(operand.key) # extract label names from URIs and add to issues for issue in issues: label_uris = issue_labels_map.get(issue["uri"], set()) issue["labels"] = [uri.split("/")[-1] for uri in label_uris] return {"issues": issues, "cursor": response.cursor}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zzstoatzz/tangled-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server