Public: anyone can read this; the crew can change it.

MCP `org_teams` with `waiting: true` answers the open pulls a team's review holds #10173

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`org_teams { org, team, waiting: true }` now answers `{ items: [{ repo, number, title, since }] }`, oldest first, at most 50, only for repositories the caller can read. The new test file, `test/mcp-orgteams.test.ts` and `test/mcp-size.test.ts` pass, and `tsc` is clean. `bun scripts/gate.ts` printed nothing, so I can't tell whether it passed. I didn't run `design-lint` or the full suite.

shipped production is serving it deploy ef71500

opened this

org_teams { org, team, waiting: true } now answers { items: [{ repo, number, title, since }] }, oldest first, at most 50, only for repositories the caller can read. The new test file, test/mcp-orgteams.test.ts and test/mcp-size.test.ts pass, and tsc is clean. bun scripts/gate.ts printed nothing, so I can't tell whether it passed. I didn't run design-lint or the full suite.

  • What it does: it asks teamsHolding in src/core/issue_teams.ts, the same question the merge gate asks, over every open pull. A held pull is listed and an approved one is not. A private repository's pull is hidden from a caller who can't read it, and an unknown team returns not_found. The tool lives in src/http/mcp/tools/org_teams.ts, with the new test in test/mcp-org-teams-waiting.test.ts.
  • Tool schema: I added a waiting boolean to the tool and made action optional. waiting: true needs no action. The tool doc says so, and docs/features/team-roles.md has a line for it. The docs/mcp/tools/ folder the issue mentions doesn't exist in the repo, so I didn't add one.
  • Which team team means: teamsHolding works on crew teams, which have a slug. Org teams have no slug and no link to crew teams. So with waiting, team is matched as a crew team by slug or name, case-insensitively. org only has to exist, and it doesn't narrow the list. If you want org teams tied to crew teams, that needs a model change.
  • Not done: I didn't find a team page that shows this list in src/web, so "the same list as the team page" is matched through teamsHolding rather than a shared function. Nothing was added on the web page or the terminal.
  • Scope: the tool still needs an admin-scope token, as before.

Closes #10163

commented

org_teams { org, team, waiting: true } now answers { items: [{ repo, number, title, since }] }, oldest first, at most 50, only for repositories the caller can read. The new test file, test/mcp-orgteams.test.ts and test/mcp-size.test.ts pass, and tsc is clean. bun scripts/gate.ts printed nothing, so I can't tell whether it passed. I didn't run design-lint or the full suite.

  • What it does: it asks teamsHolding in src/core/issue_teams.ts, the same question the merge gate asks, over every open pull. A held pull is listed and an approved one is not. A private repository's pull is hidden from a caller who can't read it, and an unknown team returns not_found. The tool lives in src/http/mcp/tools/org_teams.ts, with the new test in test/mcp-org-teams-waiting.test.ts.
  • Tool schema: I added a waiting boolean to the tool and made action optional. waiting: true needs no action. The tool doc says so, and docs/features/team-roles.md has a line for it. The docs/mcp/tools/ folder the issue mentions doesn't exist in the repo, so I didn't add one.
  • Which team team means: teamsHolding works on crew teams, which have a slug. Org teams have no slug and no link to crew teams. So with waiting, team is matched as a crew team by slug or name, case-insensitively. org only has to exist, and it doesn't narrow the list. If you want org teams tied to crew teams, that needs a model change.
  • Not done: I didn't find a team page that shows this list in src/web, so "the same list as the team page" is matched through teamsHolding rather than a shared function. Nothing was added on the web page or the terminal.
  • Scope: the tool still needs an admin-scope token, as before.
commented

org_teams { org, team, waiting: true } now lists the open pulls a crew team's review still holds, and the push after the check failure is up. The check failed only because no commit message had a Try: line. I added an empty commit with that line and pushed it. bun scripts/gate.ts printed nothing locally, and I haven't seen the forge's re-run of the check yet.

What changed

  • Answer: { items: [{ repo, number, title, since }] }, oldest first, at most 50, only from repositories the caller can read.
  • Same question as the merge gate: it uses teamsHolding from src/core/issue_teams.ts, the function behind the merge gate's team_review_required refusal. A held pull is listed and an approved one is not. A private repository's pull is hidden from a caller who can't read it, and an unknown team returns not_found.
  • Schema: the tool takes a new waiting boolean, and action is no longer required when waiting is set.
  • Docs and tests: the tool doc and docs/features/team-roles.md describe it. The tests are in test/mcp-org-teams-waiting.test.ts. They and test/mcp-size.test.ts passed on the first push.

What I chose not to do

  • team means a crew team: teamsHolding works on crew teams, and org teams have no slug or link to them. So with waiting, team is matched as a crew team by slug or name, and org only has to exist. It doesn't narrow the list.
  • No docs/mcp/tools/: that folder doesn't exist in the repo, so I documented it in the tool doc and docs/features/team-roles.md instead.
  • No web or terminal change: I found no team page in src/web that shows this list, so I didn't add the list to the web page or the terminal.
  • Admin scope: the tool still needs an admin-scope token, as before.

To try it: call the MCP tool org_teams on the preview with { org, team, waiting: true } and read items.

Changes requested — before the latest push

Changes needed, all in one round:

  1. Both doors: the feature exists only over MCP. Add the terminal screen in src/tui/ (entry where AGENTS.md says) that lists the pulls a team's review holds, with the same visibility rules, and share one function between MCP, page and terminal rather than a private waiting() inside the tool.
  2. The tool doc claims 'the team page's list', but no such page exists. Either add the web page (server-rendered, same function) or remove the claim.
  3. Box 2 asks for docs/mcp/tools/. If that folder is absent, put the how-to in docs/features/<name>.md for this feature, not only a line in team-roles.md, and say so in the pull.
  4. org is only checked to exist and does not narrow the result, and the call needs no org-admin check; a caller could pass any org name. Either tie the team to the org or document that it is global and why that is safe.
  5. Tests: add ones that fail without the behaviour for oldest-first ordering (two held pulls, check order) and the 50 cap, plus a non-admin-scope token refusal. Ordering currently depends on whatever order openPullPileRows returns and is not asserted.
  6. Box 1 names src/actions/issue_teams.ts; the code uses core/issue_teams.ts. Fine if intended, but state it.
commented

I've pushed changes for all six points to the same branch. Two of them I answered by documenting or removing rather than building, as noted below. The waiting-list tests, test/mcp-size.test.ts, test/tui-teams.test.ts, test/mcp-orgteams.test.ts, tsc and bun scripts/gate.ts all pass. I haven't seen the forge's check on this push.

  1. One shared function, and a terminal door. pullsWaitingOn(app, actor, team, limit = 50) now lives in src/actions/issue_teams.ts, and the private waiting() is gone from the MCP tool. It applies the same repository and sealed-issue visibility rules as before. It sorts oldest first by the pull's open time (then repo and number) in code instead of relying on query order. The terminal's Crew teams screen (src/tui/screens/teams.ts) has a new w key that lists the same pulls for the selected team. Crew teams is offered only to forge admins who aren't agents. I used that screen because it already exists, so I added no new palette entry.
  2. The "team page" claim is removed, and I added no web page. The tool doc now points to the terminal screen instead. I chose not to build a page nobody asked for beyond that claim. Say so if you want one.
  3. How-to doc. docs/mcp/tools/ doesn't exist, so the how-to is in docs/features/team-waiting.md. docs/features/team-roles.md links to it.
  4. org doesn't narrow the answer, and I'm leaving it that way. Crew teams are forge-wide, so I documented that org only has to exist and didn't try to tie the team to it. That is safe because results are filtered by the caller's read access to each repository. The org-admin check isn't needed either: the tool requires an admin-scope token (tested below), and the list only shows pulls the caller could already read.
  5. New tests.

- Ordering: one pull's created_at is set to 2000, and the test asserts it comes first. - Cap: limit 2 cuts the list to two. - A non-admin-scope token is refused. - The w screen shows the held pull. - The cap is tested through the limit parameter at 2, not by creating 51 pulls.

  1. core vs actions. The held-or-not decision (teamsHolding) is in src/core/issue_teams.ts. The listing function that applies the caller's access rules is in src/actions/issue_teams.ts, as the issue named.

To try it: in the terminal, open Crew teams, select a team and press w. Or call org_teams { org, team, waiting: true } over MCP.

Approved

Earlier asks are met. The listing is now one shared function, pullsWaitingOn, serving both the MCP tool and the terminal. The terminal has a w key on Crew teams. The how-to is in docs/features/team-waiting.md, and README is untouched. Ordering, cap, scope refusal, private-repo hiding and the terminal screen are each tested. Visibility goes through canRead and mayView, so it follows the caller's read access and not the org they name. Non-blocking: the terminal screen calls pullsWaitingOn on every render and keypress, which scans all open pulls. Cache the result per screen open if this gets slow. Non-blocking: the test file imports from actions/issue_teams.ts twice; merge the two lines.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs