diff --git a/.changeset/list-label-name-filter.md b/.changeset/list-label-name-filter.md new file mode 100644 index 00000000000..a2175f57e97 --- /dev/null +++ b/.changeset/list-label-name-filter.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Add an optional `nameFilter` to the `list_label` mcp-scripts pagination wrapper (and a matching `--name-filter` flag on the `github-labels-query` skill script) so agents that only need a few labels no longer pay for the full repository label set. diff --git a/.github/skills/github-labels-query/SKILL.md b/.github/skills/github-labels-query/SKILL.md index e0289f0ca20..2137036cabe 100644 --- a/.github/skills/github-labels-query/SKILL.md +++ b/.github/skills/github-labels-query/SKILL.md @@ -1,6 +1,6 @@ --- name: github-labels-query -description: List GitHub repository labels with per_page pagination support. +description: List GitHub repository labels with per_page pagination and name filtering support. --- # GitHub Labels Query Skill @@ -28,6 +28,16 @@ Use this script to list labels from any repository with controlled page sizes. ./query-labels.sh --owner github --repo gh-aw --per-page 25 --page 2 ``` +### Filtering by name + +```bash +# Only labels whose name contains "bug" (case-insensitive) +./query-labels.sh --owner github --repo gh-aw --name-filter bug +``` + +When `--name-filter` is set, all labels are fetched and filtered, then +`--per-page`/`--page` are applied to the filtered results. + ## Parameters | Parameter | Required | Default | Description | @@ -36,6 +46,7 @@ Use this script to list labels from any repository with controlled page sizes. | `--repo` | Yes | - | Repository name | | `--per-page` | No | 10 | Results per page (1–100) | | `--page` | No | 1 | Page number | +| `--name-filter` | No | - | Case-insensitive substring filter on the label name | ## Output @@ -64,3 +75,6 @@ Returns JSON with the following fields: Calls the GitHub REST API: `GET /repos/{owner}/{repo}/labels?per_page={n}&page={n}` + +When `--name-filter` is used, the script pages through all labels +(`--paginate`) before filtering and slicing locally. diff --git a/.github/skills/github-labels-query/query-labels.sh b/.github/skills/github-labels-query/query-labels.sh index daeb6a4f56e..9435c538a01 100755 --- a/.github/skills/github-labels-query/query-labels.sh +++ b/.github/skills/github-labels-query/query-labels.sh @@ -10,10 +10,11 @@ set +o histexpand # --repo REPO Repository name (required) # --per-page N Results per page: 1-100 (default: 10) # --page N Page number (default: 1) +# --name-filter STR Case-insensitive substring filter on the label name # # Alternatively, inputs can be provided as environment variables using the # mcp-scripts INPUT_* convention (INPUT_OWNER, INPUT_REPO, INPUT_PERPAGE, -# INPUT_PAGE). INPUT_PER_PAGE is also accepted for backward compatibility. +# INPUT_PAGE, INPUT_NAMEFILTER). INPUT_PER_PAGE is also accepted for backward compatibility. # CLI arguments take precedence over environment variables. # # Calls the GitHub REST API: @@ -32,6 +33,7 @@ OWNER="${INPUT_OWNER:-}" REPO="${INPUT_REPO:-}" PER_PAGE="${INPUT_PERPAGE:-${INPUT_PER_PAGE:-10}}" PAGE="${INPUT_PAGE:-1}" +NAME_FILTER="${INPUT_NAMEFILTER:-}" while [[ $# -gt 0 ]]; do case $1 in @@ -51,6 +53,10 @@ while [[ $# -gt 0 ]]; do PAGE="$2" shift 2 ;; + --name-filter) + NAME_FILTER="$2" + shift 2 + ;; *) echo "Unknown option: $1" >&2 exit 1 @@ -73,14 +79,23 @@ if ! [[ "$PER_PAGE" =~ ^[0-9]+$ ]] || [[ "$PER_PAGE" -lt 1 ]] || [[ "$PER_PAGE" exit 1 fi -RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") +if [[ -n "$NAME_FILTER" ]]; then + RESPONSE=$(gh api --paginate --slurp "repos/${OWNER}/${REPO}/labels?per_page=100" | jq '[.[][]]') +else + RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") +fi echo "$RESPONSE" | jq \ --argjson per_page "$PER_PAGE" \ --argjson page "$PAGE" \ - '{ - labels: [.[] | {id, node_id, url, name, color, default, description}], - item_count: length, + --arg name_filter "$NAME_FILTER" \ + '(if $name_filter == "" then . + else [.[] | select(.name | ascii_downcase | contains($name_filter | ascii_downcase))] + | .[(($page - 1) * $per_page):($page * $per_page)] + end) as $selected + | { + labels: [$selected[] | {id, node_id, url, name, color, default, description}], + item_count: ($selected | length), per_page: $per_page, page: $page }' diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index 385b94e4a4d..88a0e9d511f 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"edcdc0f024ee3ab0298171a1d7c1ffd8e07a37a34de8a16a6e990725e478d758","body_hash":"2b2cec4250bfd0b0e95df7aa5981e3dd0f3945bd4a83b41079f970a8559a8c7d","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.220"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"58bb45bfbdc951ebc9aad17ccd58ed6b7faf621ce407f228ff42d6a413b5803f","body_hash":"bf76222e0b87f514ee362bacac1fdce725772e4da1abeb3a1cc18c768c267e93","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.220"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"b7ad1dad31e06c5925ef5d2fc7ad053ef454303e","version":"v7.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"53b7df96c91f9c12dcc8a07bcb9ccacbed38856a","version":"v7.3.0"},{"repo":"docker/setup-buildx-action","sha":"bb05f3f5519dd87d3ba754cc423b652a5edd6d2c","version":"v4.2.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44","digest":"sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44","digest":"sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.44","digest":"sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.44@sha256:c064d15974f7c933ec7d3f7b4038f4fd203547b3154bdc821afd379144887eff"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44","digest":"sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"},{"image":"node:lts-alpine","digest":"sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43","pinned_image":"node:lts-alpine@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -1093,7 +1093,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_f5a5e76e6c546226_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_812c03860ef9021e_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -1101,9 +1101,13 @@ jobs: "tools": [ { "name": "list_label", - "description": "List labels in a GitHub repository with perPage pagination support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses.", + "description": "List labels in a GitHub repository with perPage pagination and name filtering support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses.", "inputSchema": { "properties": { + "nameFilter": { + "description": "Case-insensitive substring filter on the label name. When set, all labels are scanned and only matching labels are paginated.", + "type": "string" + }, "owner": { "description": "Repository owner (username or organization)", "type": "string" @@ -1169,7 +1173,7 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_f5a5e76e6c546226_EOF + GH_AW_MCP_SCRIPTS_TOOLS_812c03860ef9021e_EOF cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_e0a10bf70e571677_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); @@ -1189,10 +1193,10 @@ jobs: - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_e74f76f3215a6b0b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_cc543361a716f0bb_EOF' #!/bin/bash # Auto-generated mcp-script tool: list_label - # List labels in a GitHub repository with perPage pagination support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses. + # List labels in a GitHub repository with perPage pagination and name filtering support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses. set +o histexpand set -euo pipefail @@ -1203,6 +1207,7 @@ jobs: REPO="${INPUT_REPO:-}" PER_PAGE="${INPUT_PERPAGE:-10}" PAGE="${INPUT_PAGE:-1}" + NAME_FILTER="${INPUT_NAMEFILTER:-}" if [[ -z "$OWNER" ]]; then echo '{"error": "owner is required"}' >&2 @@ -1224,20 +1229,29 @@ jobs: exit 1 fi - RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + if [[ -n "$NAME_FILTER" ]]; then + RESPONSE=$(gh api --paginate --slurp "repos/${OWNER}/${REPO}/labels?per_page=100" | jq '[.[][]]') + else + RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + fi echo "$RESPONSE" | jq \ --argjson per_page "$PER_PAGE" \ --argjson page "$PAGE" \ - '{ - labels: [.[] | {id, node_id, url, name, color, default, description}], - item_count: length, + --arg name_filter "$NAME_FILTER" \ + '(if $name_filter == "" then . + else [.[] | select(.name | ascii_downcase | contains($name_filter | ascii_downcase))] + | .[(($page - 1) * $per_page):($page * $per_page)] + end) as $selected + | { + labels: [$selected[] | {id, node_id, url, name, color, default, description}], + item_count: ($selected | length), per_page: $per_page, page: $page }' - GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_e74f76f3215a6b0b_EOF + GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_cc543361a716f0bb_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_workflows.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_WORKFLOWS_0c08b61cc6f71742_EOF' #!/bin/bash diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml index f46cae72bd4..4cdf21f42f9 100644 --- a/.github/workflows/github-mcp-structural-analysis.lock.yml +++ b/.github/workflows/github-mcp-structural-analysis.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3e23111997930b5282b5fe3fba686b4f3beedfa0c71b4c3da77d211de47697d0","body_hash":"52df15ed546c1eb02b6a3d2720f1cd1f64e426f770b17e11c5242f10f55c24bb","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.220"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"b50f4419053a147e942eeed71dc385921d9dc41de1ae8ba4c848400cdb6bbed6","body_hash":"1f7a03fe63936db3e4c102bfd8ce6ec8b122e8c9759dab1997391fe5751bb258","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.220"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/setup-python","sha":"5fda3b95a4ea91299a34e894583c3862153e4b97","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44","digest":"sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.44@sha256:0d727725c737b58c7bdf51f640cffb928385ec46517e0917c7f1a02f1bada8b4"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44","digest":"sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.44@sha256:b50fbadba138f6e9aba94aca09711335c489bb3b15861220cb66f6092e042dc7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44","digest":"sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.44@sha256:83e48bbe12c634be8c228a576832fe45f66c529ac3659db92bddbcf2eeb6d627"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.8","digest":"sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.8@sha256:38bbea36cdb46a3c9d04d1db05e672966f5239b431a2022eb35881688e5721d8"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -747,7 +747,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_f5a5e76e6c546226_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_812c03860ef9021e_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -755,9 +755,13 @@ jobs: "tools": [ { "name": "list_label", - "description": "List labels in a GitHub repository with perPage pagination support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses.", + "description": "List labels in a GitHub repository with perPage pagination and name filtering support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses.", "inputSchema": { "properties": { + "nameFilter": { + "description": "Case-insensitive substring filter on the label name. When set, all labels are scanned and only matching labels are paginated.", + "type": "string" + }, "owner": { "description": "Repository owner (username or organization)", "type": "string" @@ -823,7 +827,7 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_f5a5e76e6c546226_EOF + GH_AW_MCP_SCRIPTS_TOOLS_812c03860ef9021e_EOF cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_e0a10bf70e571677_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); @@ -843,10 +847,10 @@ jobs: - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_e74f76f3215a6b0b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_cc543361a716f0bb_EOF' #!/bin/bash # Auto-generated mcp-script tool: list_label - # List labels in a GitHub repository with perPage pagination support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses. + # List labels in a GitHub repository with perPage pagination and name filtering support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses. set +o histexpand set -euo pipefail @@ -857,6 +861,7 @@ jobs: REPO="${INPUT_REPO:-}" PER_PAGE="${INPUT_PERPAGE:-10}" PAGE="${INPUT_PAGE:-1}" + NAME_FILTER="${INPUT_NAMEFILTER:-}" if [[ -z "$OWNER" ]]; then echo '{"error": "owner is required"}' >&2 @@ -878,20 +883,29 @@ jobs: exit 1 fi - RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + if [[ -n "$NAME_FILTER" ]]; then + RESPONSE=$(gh api --paginate --slurp "repos/${OWNER}/${REPO}/labels?per_page=100" | jq '[.[][]]') + else + RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + fi echo "$RESPONSE" | jq \ --argjson per_page "$PER_PAGE" \ --argjson page "$PAGE" \ - '{ - labels: [.[] | {id, node_id, url, name, color, default, description}], - item_count: length, + --arg name_filter "$NAME_FILTER" \ + '(if $name_filter == "" then . + else [.[] | select(.name | ascii_downcase | contains($name_filter | ascii_downcase))] + | .[(($page - 1) * $per_page):($page * $per_page)] + end) as $selected + | { + labels: [$selected[] | {id, node_id, url, name, color, default, description}], + item_count: ($selected | length), per_page: $per_page, page: $page }' - GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_e74f76f3215a6b0b_EOF + GH_AW_MCP_SCRIPTS_SH_LIST_LABEL_cc543361a716f0bb_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_label.sh" cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/list_workflows.sh" << 'GH_AW_MCP_SCRIPTS_SH_LIST_WORKFLOWS_0c08b61cc6f71742_EOF' #!/bin/bash diff --git a/.github/workflows/shared/github-mcp-pagination-wrappers.md b/.github/workflows/shared/github-mcp-pagination-wrappers.md index f54c2c2783e..eb172af22cb 100644 --- a/.github/workflows/shared/github-mcp-pagination-wrappers.md +++ b/.github/workflows/shared/github-mcp-pagination-wrappers.md @@ -62,7 +62,7 @@ mcp-scripts: }' list_label: - description: "List labels in a GitHub repository with perPage pagination support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses." + description: "List labels in a GitHub repository with perPage pagination and name filtering support. Returns labels array, item_count, per_page, and page. Defaults to perPage=10 to avoid large responses." inputs: owner: type: string @@ -80,6 +80,10 @@ mcp-scripts: type: number description: "Page number (default: 1)" required: false + nameFilter: + type: string + description: "Case-insensitive substring filter on the label name. When set, all labels are scanned and only matching labels are paginated." + required: false env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -89,6 +93,7 @@ mcp-scripts: REPO="${INPUT_REPO:-}" PER_PAGE="${INPUT_PERPAGE:-10}" PAGE="${INPUT_PAGE:-1}" + NAME_FILTER="${INPUT_NAMEFILTER:-}" if [[ -z "$OWNER" ]]; then echo '{"error": "owner is required"}' >&2 @@ -110,14 +115,23 @@ mcp-scripts: exit 1 fi - RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + if [[ -n "$NAME_FILTER" ]]; then + RESPONSE=$(gh api --paginate --slurp "repos/${OWNER}/${REPO}/labels?per_page=100" | jq '[.[][]]') + else + RESPONSE=$(gh api "repos/${OWNER}/${REPO}/labels?per_page=${PER_PAGE}&page=${PAGE}") + fi echo "$RESPONSE" | jq \ --argjson per_page "$PER_PAGE" \ --argjson page "$PAGE" \ - '{ - labels: [.[] | {id, node_id, url, name, color, default, description}], - item_count: length, + --arg name_filter "$NAME_FILTER" \ + '(if $name_filter == "" then . + else [.[] | select(.name | ascii_downcase | contains($name_filter | ascii_downcase))] + | .[(($page - 1) * $per_page):($page * $per_page)] + end) as $selected + | { + labels: [$selected[] | {id, node_id, url, name, color, default, description}], + item_count: ($selected | length), per_page: $per_page, page: $page }' @@ -133,7 +147,10 @@ The built-in `list_label` GitHub MCP tool returns up to 100 labels regardless of `list_workflows` built-in GitHub MCP tool uses a non-standard `per_page` parameter (snake_case), inconsistent with every other list-style MCP tool which uses camelCase `perPage`, and the limit was silently ignored. These wrappers call the GitHub REST API -directly so `perPage` is respected on every call, using the camelCase convention. +directly so `perPage` is respected on every call, using the camelCase convention. The `list_label` +wrapper also accepts an optional `nameFilter` so callers that only need a handful of +labels (for example triage workflows checking a few known names) do not pay for the +full label set. ### Available Tools @@ -168,6 +185,7 @@ imports: | repo | string | Yes | - | Repository name | | perPage | number | No | 10 | Results per page (1–100) | | page | number | No | 1 | Page number | +| nameFilter | string | No | - | Case-insensitive substring filter on the label name | ### list_workflows Response