Skip to content

date: 2026-06-06 tags: [github, projects, status, graphql, triage, web-env] status: active graduated_to:

Projects v2 Status is writable from the web env — via GraphQL + $GH_TOKEN, not the MCP server

Symptomtriage assumed the readiness Status couldn't be set in the Claude Code web/remote env: the GitHub MCP server exposes no Projects-v2 tool, there's no gh CLI, and an unauthenticated api.github.com hit 403s — so Status was only ever reported, never applied.

Root cause — Status is a Projects v2 board field; the native Issues REST API (and the MCP issue_write / list_issue_fields) only reach issue fields like Area, never a project's per-board Status. Projects v2 is GraphQL-only. The 403 was just missing auth — the env's $GH_TOKEN authenticates fine and carries project-write scope.

Fix — set Status with the GraphQL updateProjectV2ItemFieldValue mutation against https://api.github.com/graphql, header Authorization: Bearer $GH_TOKEN. The issue must be a board item (it is, once added to the project); read its item id via repository.issue(number:){ projectItems(first:10){ nodes { id project { id } } } }. Reusable IDs for org Project v2 #3 "Tempo":

  • project: PVT_kwDOEVOzGc4BZyyo
  • Status field: PVTSSF_lADOEVOzGc4BZyyozhUvAaU
  • options: Needs Triage 209ea7d2 · Needs Info eddb06eb · Ready for Agent 03206af8 · Ready for Human 7d192ed2 · In Progress 47fc9ee4 · Done 98236657 · Wontfix 7575332d

Re-discover with node(id:"<project>"){ ... on ProjectV2 { fields(first:50){ nodes { ... on ProjectV2SingleSelectField { id name options { id name } } } } } } if the board changes.

Guard.claude/skills/triage/SKILL.md and docs/agents/triage-labels.md now say apply Status via this mutation, not just recommend it. Complements [[2026-06-05-github-native-typed-backlog-api]] (REST issue-type / sub-issue / dependency primitives) and [[2026-06-05-agent-identity-two-layers]] (the token side).