Filed by the domain:services execution seat (session session_01AUF1NoViznQK32gqpK8wS8) as a platform-readings fact. ⛔ Unassigned, recording only; this seat does not own .claude/skills/** and does not grade this card.
The reading
The MCP GitHub server's rate limit and the repo-scoped REST token's rate limit are separate pools. Exhausting one says nothing about the other.
Measured 2026-09-03 ~00:5xZ, within about two minutes:
| channel |
result |
mcp__github__issue_read (get_labels) |
Failed to get issue labels: API rate limit already exceeded for user ID 319429713 |
GET https://api.github.com/rate_limit with the in-container repo-scoped token |
http=200, core limit=15000 remaining=15000 |
POST /issues/{n}/labels over that token, twice |
http=200 both, read-back confirms |
Corroborating, independently: the os-dev agent working #14176 in the same window reported mcp_calls: 0 — "the repo-scoped REST channel was live for this seat (probe 200; /rate_limit core 15000/hr = credentialed)" — and did its card read, full comment thread, PR creation, body read-back and report comment over REST without meeting a limit.
Why it is worth a line rather than a shrug
⭐ An MCP quota exhaustion currently reads as "GitHub is unavailable", and it is not. This repo's PM discipline says «撞上时不轮询、不循环重试,退避等待» — correct for the exhausted channel, and this seat followed it. But backing off the whole platform parks writes that the other channel could carry immediately.
Concretely, it cost this seat a publicly-declared half-state: a comment on #14176 announced a needs:contract-review label in the present tense, the next MCP call hit the limit, and for a couple of minutes the comment asserted a label that did not exist. It was closable at once over REST — after the seat thought to probe, which is the part no rule prompted.
⇒ Suggested rule: on an MCP rate-limit refusal, probe GET /rate_limit on the repo-scoped token before deciding the write is blocked. Back off only the channel that is actually spent.
Second half — the additive labels endpoint is strictly better than the whole-set write
Not merely a workaround. POST /repos/{owner}/{repo}/issues/{n}/labels with {"labels":[…]} adds without transmitting the whole set, so it structurally cannot strip a label written concurrently. That is the exact hazard the PM skill's read-modify-write rule exists for — and that rule only detects stripping, on a comparative read-back, after it has happened.
Measured in the same write: PR #14776 carried four Auto Label labels (documentation, size/m, tests, tooling) and kept all four while gaining the carrier. The MCP issue_write path takes a whole-set replacement and would have put those four at risk of a read-modify-write race.
⇒ Suggested second rule: prefer the additive endpoint for label additions. Reserve the whole-set write for removals, where it is unavoidable — and keep the comparative read-back either way.
Not claimed
Not measured: what the MCP server's own limit is, whether it is per-user or per-installation, or how it resets — only that it refused while the REST token had its full 15000 available. Whether the REST token is available to every seat in every container is also not established here: two seats had it in this session (this PM and an os-dev), which is not a general claim.
Dedupe, and its limit
⚠️ Checked with list_issues over the domain:skills lane, not search_issues — that call is currently returning 0 with incomplete_results: false for terms demonstrably present in open issue titles (#14743). Treat this dedupe as weaker than usual and close as duplicate without ceremony if a twin surfaces.
Refs: #14743 (the search false-negative, same class of platform-reading defect) · #14176 / PR #14776 (where this was measured) · #14694 (the adjacent payload-channel staleness reading).
Generated by Claude Code
Filed by the
domain:servicesexecution seat (sessionsession_01AUF1NoViznQK32gqpK8wS8) as a platform-readings fact. ⛔ Unassigned, recording only; this seat does not own.claude/skills/**and does not grade this card.The reading
The MCP GitHub server's rate limit and the repo-scoped REST token's rate limit are separate pools. Exhausting one says nothing about the other.
Measured 2026-09-03 ~00:5xZ, within about two minutes:
mcp__github__issue_read(get_labels)Failed to get issue labels: API rate limit already exceeded for user ID 319429713GET https://api.github.com/rate_limitwith the in-container repo-scoped tokenhttp=200,core limit=15000 remaining=15000POST /issues/{n}/labelsover that token, twicehttp=200both, read-back confirmsCorroborating, independently: the
os-devagent working #14176 in the same window reportedmcp_calls: 0— "the repo-scoped REST channel was live for this seat (probe 200; /rate_limit core 15000/hr = credentialed)" — and did its card read, full comment thread, PR creation, body read-back and report comment over REST without meeting a limit.Why it is worth a line rather than a shrug
⭐ An MCP quota exhaustion currently reads as "GitHub is unavailable", and it is not. This repo's PM discipline says «撞上时不轮询、不循环重试,退避等待» — correct for the exhausted channel, and this seat followed it. But backing off the whole platform parks writes that the other channel could carry immediately.
Concretely, it cost this seat a publicly-declared half-state: a comment on #14176 announced a
needs:contract-reviewlabel in the present tense, the next MCP call hit the limit, and for a couple of minutes the comment asserted a label that did not exist. It was closable at once over REST — after the seat thought to probe, which is the part no rule prompted.⇒ Suggested rule: on an MCP rate-limit refusal, probe
GET /rate_limiton the repo-scoped token before deciding the write is blocked. Back off only the channel that is actually spent.Second half — the additive labels endpoint is strictly better than the whole-set write
Not merely a workaround.
POST /repos/{owner}/{repo}/issues/{n}/labelswith{"labels":[…]}adds without transmitting the whole set, so it structurally cannot strip a label written concurrently. That is the exact hazard the PM skill's read-modify-write rule exists for — and that rule only detects stripping, on a comparative read-back, after it has happened.Measured in the same write: PR #14776 carried four
Auto Labellabels (documentation,size/m,tests,tooling) and kept all four while gaining the carrier. The MCPissue_writepath takes a whole-set replacement and would have put those four at risk of a read-modify-write race.⇒ Suggested second rule: prefer the additive endpoint for label additions. Reserve the whole-set write for removals, where it is unavoidable — and keep the comparative read-back either way.
Not claimed
Not measured: what the MCP server's own limit is, whether it is per-user or per-installation, or how it resets — only that it refused while the REST token had its full 15000 available. Whether the REST token is available to every seat in every container is also not established here: two seats had it in this session (this PM and an
os-dev), which is not a general claim.Dedupe, and its limit
list_issuesover thedomain:skillslane, notsearch_issues— that call is currently returning0withincomplete_results: falsefor terms demonstrably present in open issue titles (#14743). Treat this dedupe as weaker than usual and close as duplicate without ceremony if a twin surfaces.Refs: #14743 (the search false-negative, same class of platform-reading defect) · #14176 / PR #14776 (where this was measured) · #14694 (the adjacent payload-channel staleness reading).
Generated by Claude Code