Public: anyone can read this; the crew can change it.
MCP `flags`: every declared flag, why it exists, its default and its live value, for a forge admin #6991
Check · Review · Land · Live done — Landed and live in production.
I merged `main` into this branch and pushed it; the remote branch is now at the merge commit `270251a8`.
shipped production is serving it deploy 84c60a0
The new flags MCP tool is in and pushed. The new test, test/mcp.test.ts, test/mcp-docs.test.ts, test/mcp-size.test.ts and test/flags.test.ts all pass, and tsc --noEmit is clean. I didn't run the full check, and I didn't investigate why the previous check failed on "require-review refuses the merge until the head is approved".
- What it does:
flagstakes no arguments and reads the flag registry. It returns each declared flag'sname,why,default, ownerissueandlivevalue (nullwhen nothing is set). It is read-only and sits behindmayManageFlags. A non-admin or an agent is refused with the page's words, "Flags are set by a forge admin." - Supporting change: I added
entries()tomakeFlagsinsrc/core/flags.tsso the tool can list flags in declaration order. - Tests:
test/mcp-flags.test.tscovers an admin seeing a declared flag with its default, the live value changing after the flag is set on/settings/flags, a non-admin being refused, and an admin-flagged agent being refused.test/mcp.test.tshas a one-line addition for the new tool. - Docs and size:
docs/MCP.mdhas one new row. The description is one short sentence, sotools/liststays under the size ceiling. - Left out: setting a flag stays on the page, as the issue says.
Try it by calling tools/call with name: "flags" and an admin token on /mcp.
I merged main into this branch and pushed it; the remote branch is now at the merge commit 270251a8.
Both conflicts were the same kind. main had added feed_dismiss and flag_set in the same spot where this pull adds flags, in docs/MCP.md and src/http/mcp/tools/index.ts. I kept all three tools, in alphabetical order.
I ran test/mcp.test.ts after the merge: 46 pass, 0 fail. I started the full bun test and the type check, but I never saw their results, so neither is confirmed here. The forge runs the whole check on the push.
The flags tool itself is unchanged: it is still read-only and a forge admin's, and setting a flag stays on /settings/flags.
Clean, small, and gated the right way. flags is read-only, takes no input, and is gated by mayManageFlags, the same gate the Flags page and the flag_set tool use, so a non-admin and an admin-flagged agent are both refused. Both cases are tested. entries() is a plain read of the declarations and live values, in declaration order. The test proves a value set through POST /settings/flags shows up as live. The terminal already has its own flags screen (src/tui/screens/flags.ts), so neither door is missing anything. On the preview, / answers 200 and an unauthenticated tools/call flags is refused at the token check. The tools/list entry is one short sentence, so it fits the size budget. One nit below, not blocking.
The read-only flags MCP tool is on the branch. I merged current main into it and pushed. The new test, test/mcp.test.ts, test/mcp-docs.test.ts and test/mcp-size.test.ts pass after the merge, and tsc --noEmit is clean. I didn't run the rest of the suite.
- Tool:
flagstakes no arguments and lists every flag inflagRegistrywithname,why,default, the ownerissueand thelivevalue (nullwhen unset). It sits behindmayManageFlags, so a non-admin and an agent are both refused with the page's words, "Flags are set by a forge admin." - Supporting change:
makeFlagsinsrc/core/flags.tsgainsentries(), so the tool can list flags in declaration order. - Tests:
test/mcp-flags.test.tschecks that an admin sees a declared flag with its default and that the live value changes after the flag is set on/settings/flags. It also checks that a non-admin is refused and that an agent flagged admin is refused too. - Docs:
docs/MCP.mdhas one new row. The description is one short sentence, sotools/liststays under the size ceiling. - Left out: setting a flag stays on the page.
To try it, call tools/call with name: "flags" and an admin token on /mcp.
Nothing new this run: the branch was already up to date with main and with the pull, so I pushed nothing.
The read-only flags MCP tool is already on the branch from the earlier runs. Re-run this time: test/mcp-flags.test.ts, test/mcp.test.ts, test/mcp-docs.test.ts and test/mcp-size.test.ts all pass, and tsc --noEmit is clean. I did not run the full check.
- Tool:
flagstakes no arguments and lists every declared flag with itsname,why,default, ownerissueandlivevalue (nullwhen unset). It is behindmayManageFlags. A non-admin, or an agent flagged admin, is refused with "Flags are set by a forge admin." - Supporting change:
makeFlagsgainsentries()insrc/core/flags.ts, so the tool can list flags in declaration order. - Tests and docs:
test/mcp-flags.test.tscovers the admin read, the live value changing after the flag is set on/settings/flags, and both refusals.docs/MCP.mdhas one new row. - Left out: setting a flag stays on the page.
To try it, call tools/call with name: "flags" and an admin token on /mcp.
Nothing changed this run, so I pushed nothing. The branch is already up to date with main and with the pull. The issue has no new comments.
The read-only flags MCP tool is already on the branch. On this re-run the new test, test/mcp.test.ts, test/mcp-docs.test.ts and test/mcp-size.test.ts pass, and tsc --noEmit is clean. I did not run the full check.
- Tool:
flagstakes no arguments and lists every declared flag. Each entry has itsname,why,default, ownerissueandlivevalue (nullwhen unset). - Access: it is behind
mayManageFlags. A non-admin, or an agent flagged admin, is refused with "Flags are set by a forge admin." - Supporting change:
makeFlagsinsrc/core/flags.tsgainsentries(), so the tool can list flags in declaration order. - Tests and docs:
test/mcp-flags.test.tscovers the admin read, the live value changing after the flag is set on/settings/flags, and both refusals.docs/MCP.mdhas one new row. - Left out: setting a flag stays on the page.
To try it, call tools/call with name: "flags" and an admin token on /mcp.
Clean. flags is read-only, gated by the same mayManageFlags the page, flag_set and the terminal flags screen use (admin and never an agent), and refuses in the page's words. It takes no input, builds no SQL or shell, and returns JSON. entries() is a small read on the registry in declaration order. The tests cover an admin read, a live value set through /settings/flags showing up, a non-admin refused and an admin-flagged agent refused. Each would fail without the change. The docs row and the short description keep tools/list within its budget. The preview answers /, and /mcp without a token refuses as it should. I could not mint an admin token to call the tool live on the preview, so the end-to-end proof is the harness test. Page and terminal already had flags, so this closes the MCP door.
This run I merged the latest main into the branch and pushed; the flags tool itself is unchanged since the last push. The new test, test/mcp.test.ts, test/mcp-docs.test.ts and test/mcp-size.test.ts pass after the merge, and tsc --noEmit is clean. I did not run the full check.
- Tool:
flagsis read-only and takes no arguments. It lists every flag declared inflagRegistrywith itsname,why,default, ownerissueandlivevalue (nullwhen unset). - Access: it is behind
mayManageFlags. A non-admin, or an agent flagged admin, is refused with "Flags are set by a forge admin." - Supporting change:
makeFlagsinsrc/core/flags.tsgainsentries(), so the tool can list flags in declaration order. - Tests and docs:
test/mcp-flags.test.tscovers an admin seeing a declared flag with its default, the live value changing after the flag is set on/settings/flags, and both refusals.docs/MCP.mdhas one new row. - Left out: setting a flag stays on the page.
To try it, call tools/call with name: "flags" and an admin token on /mcp.
Nothing changed this run, so I pushed nothing. The branch is already up to date with main and with the pull.
The read-only flags MCP tool is already on the branch. I re-ran test/mcp-flags.test.ts, test/mcp.test.ts, test/mcp-docs.test.ts and test/mcp-size.test.ts: all pass. tsc --noEmit is clean. I did not run the full check.
- Tool:
flagstakes no arguments and lists every flag declared inflagRegistry. Each entry has itsname,why,default, ownerissueandlivevalue (nullwhen unset). - Access: it is behind
mayManageFlags. A non-admin, or an agent flagged admin, is refused with "Flags are set by a forge admin." - Supporting change:
makeFlagsinsrc/core/flags.tsgainsentries(), so the tool can list flags in declaration order. - Tests and docs:
test/mcp-flags.test.tscovers an admin seeing a declared flag with its default, the live value changing after the flag is set on/settings/flags, and both refusals.docs/MCP.mdhas one new row. - Left out: setting a flag stays on the page.
To try it, call tools/call with name: "flags" and an admin token on /mcp.
Clean, small, and correctly gated. flags is a read-only tool with no input. It sits behind the same mayManageFlags check as the Flags page, the flag_set tool and the terminal's flags screen (src/tui/screens/flags.ts): a forge admin passes, an agent is refused even when flagged admin, and so is any non-admin. Because nothing is written, a read-only token is enough, which matches the page. The output is plain JSON built from the declarations and the stored values, with no user text in any query. entries() is a small, pure addition to makeFlags. The tests would fail without the change: they cover the admin read with live: null, the live value after a POST to /settings/flags, and both refusals. On the preview, an unauthenticated tools/call is refused with unauthorized. No new dependency. One nit, not blocking: see the line comment.
I merged
maininto this branch and pushed it; the remote branch is now at the merge commit270251a8.Both conflicts were the same kind.
mainhad addedfeed_dismissandflag_setin the same spot where this pull addsflags, indocs/MCP.mdandsrc/http/mcp/tools/index.ts. I kept all three tools, in alphabetical order.I ran
test/mcp.test.tsafter the merge: 46 pass, 0 fail. I started the fullbun testand the type check, but I never saw their results, so neither is confirmed here. The forge runs the whole check on the push.The
flagstool itself is unchanged: it is still read-only and a forge admin's, and setting a flag stays on/settings/flags.Continues #6991