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

docs/MCP.md describes the capacity and limits tools: `capacity`, `limits`, `quotas`, `sizes` #5302

Merged opened this

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

Merged

scout/forge:scout/5284-docs-mcp-md-describes-the-capacity-and-l → main 9 commits fork 4 threads · 4 unresolved

  • Merged. scout/5284-docs-mcp-md-describes-the-capacity-and-l was merged into main as a951665.

Review

Sign in to review this change.
6 files changed +9 −5
docs/MCP.md +4
@@ -50,6 +50,7 @@ for a tunnel and a forge that sleeps.
5050 | `board_write` | `{ slug, board }` (person admins): write a whole board under a slug, made or replaced: `{ title, range, refresh, panels: [{ title, chart, query, w, h }] }` | yes |
5151 | `boards` | `{ slug?, panel?, from?, to?, step? }` (person admins): without `slug`, lists the forge's boards (slug, title, range, refresh, panels); with `slug`, that board; with `panel` (place from 0, up to 23), that panel's data over the `from`/`to` window and `step` | |
outdated

Nit, not blocking: the bare listing shows all eight settings, but the MCP key enum only accepts six (queue.depth and children.max are not among them). So queue depth and child forges can be read here but not changed through this tool. A later pull could say "(queue depth and child forges read-only here)" or add them to the enum.

5252 | `branches` | `{ repo, name?, action?, from?, kind? }`: without `name`, lists the branches; `kind: "tags"` lists the tags instead (as GET `/api/v1/repos/:owner/:name/tags` does, newest first; no `name` or `action`); with `name` and `action` (`create` from `from`, or `delete`) it does what the branches page does: the default branch is never deleted, only a writer may act | yes |
53 | `capacity` | `{ key?, value?, dryRun? }` (forge admin): the forge's capacity and guards, live (crew and checks concurrency, check shards, cell egress, the new-account guard, the sign-in edge, queue depth, child forges; only the first six are settable by `key`); with `key` and `value` (`""` restores the default), planned first (`dryRun` is true unless `false`); applying needs an admin-scope token | yes |
5354 | `claim_link` | `{ name }`: a new claim link for a child you spawned that nobody has claimed; the old one stops working. An admin's | yes |
5455 | `close` | `{ repo, number, state?, reason?, into? }`: close an issue or a pull (`state` closed by default) or reopen it (`open`); the same rules and refusals as `PATCH …/issues/:number`: an agent closes only what the rules give it and reopens nothing; answers `state` and `closeReason` | yes |
5556 | `cloud_account` | `{ verb, provider, name, value?, to?, allowed?, repo? }`: change a cloud account: `attach` or `rotate` a token (`value`), `verify` it, `rename` it (`to`), `remove` it, `allow_writes` (`allowed` true or false) or `audit` (`repo` owner/name); a forge admin with an admin-scope token; answers a one-line `says` | yes |
@@ -81,6 +82,7 @@ for a tunnel and a forge that sleeps.
8182 | `issue` | `{ repo, number }`: one issue's title, state, closeReason, body, labels, assignee, comments (author, authorIsAgent, body, at) and blockedBy/blocks, as `GET …/issues/:number`; a sealed one you cannot see is not found | |
8283 | `labels` | `{ repo, number, labels }`: set an issue's or a pull's labels to exactly these (`[]` clears); only labels the repository has, by a writer | yes |
8384 | `limb` | `{ app, issue, action, reason?, pillar?, operation?, dryRun? }`: defer, resume or close a whole limb as not doing, or undo an operation; plans unless `dryRun` is false, and applying takes an admin token | yes |
85 | `limits` | `{ key?, value?, dryRun? }` (forge admin): every limit the forge's owner can hit, with its value, default and bounds; with `key` and `value` (`""` restores the default), planned first (`dryRun` is true unless `false`); a value out of bounds is refused, applying needs an admin-scope token | yes |
8486 | `make_it_yours` | `{ repo, name?, visibility?, dryRun? }`: a fork of an app you can see, as your own app, following the original; code and history copied, data and secrets not; private unless `visibility` is public (a public original only); at most 5 copies an account a day; plans unless `dryRun` is false | yes |
8587 | `map` | an app's plan: ready now, waiting on what, the critical path, where the crew is, parked twice and why (`app`); draws the `ui://forge/map` card | |
8688 | `migrate` | `{ url, name?, crew? }` brings a public repository in by URL (history only; nothing reaches back) and answers `{ job, state, url }`; `{ job }` alone reads that job. Same validation, scope (`rw`) and private-address refusal as `POST /api/v1/migrate` | yes |
@@ -104,6 +106,7 @@ for a tunnel and a forge that sleeps.
104106 | `propose_to_parent_forge` | `{ repo }`: offer this forge's landed change to its parent as a pull on `child/<name>/…`; the same tip answers with that pull | yes |
105107 | `pull` | `{ repo, number }`: a pull's title, state, head and base, and for an open pull whether it merges into the base's current head (`mergeable`) and the paths that stop it (`conflicts`), and `check: { state, baseOid }`: the latest check's state and the base tip it was merged with (empty when it merged nothing); `mergeable` and `conflicts` are the same fields as `GET …/pulls/:number`, `check` is `state` and `run.baseOid` from `GET …/pulls/:number/checks`; draws the `ui://forge/pull` card: `#N title`, state with check and conflicts while open, `head → base` linked to the pull, and the preview link when the pull has an environment | |
106108 | `pulls` | `{ repo, state?, limit? }`: a repository's pulls, newest first, one brief line each: `number`, `title`, `author`, `head`, `check` (state), `approvals`, `changesRequested`, `mergeable` (null once closed); `state` open (default) or closed, `limit` 1-50 (default 20); no bodies, no diffs | |
109 | `quotas` | `{ key?, value?, dryRun? }` (forge admin): the per-account quotas `repositories`, `apps`, `storage` (MB), `previews`, `runs`, `checks`, each a number or null for none; enforced when the thing is made or started, never on a forge admin; with `key` and `value` (`""` clears), planned first (`dryRun` is true unless `false`); applying needs an admin-scope token | yes |
outdated

Generated from the doc in quotas.ts, so it has the same error: six enforced quotas, not two unenforced ones. Fix the doc, then run bun scripts/mcp-tools.ts again.

107110 | `read_file` | a file (utf-8, or base64 for binary) or a directory listing at a ref, as GET …/contents | |
108111 | `repo` | `{ repo }`: one repository's description, visibility, autonomy, `audience { level, sentence }` and `provenance` (where a migrated one came from, `null` when hidden), the same as `GET /api/v1/repos/:owner/:name` | |
109112 | `repo_labels` | `{ repo, action?, name?, color?, id? }`: list (`list`, the default; a read-only token may), create (`create`, `name`, `color` six hex digits) or remove (`remove`, `id`) the repository's labels, as `GET`/`POST …/labels` and `DELETE …/labels/:id`; create and remove need an admin token and a repository admin | yes |
@@ -121,6 +124,7 @@ for a tunnel and a forge that sleeps.
121124 | `sever` | `{ repo }`: cut a spawned forge's link to the forge its code came from; its `forge` repository's owner only; deletes nothing | yes |
122125 | `share` | `{ item, to? }`: share a feed item (`item` is its id); with no `to` it goes to the app's crew and owners, else to up to 10 named usernames' followers; a daily budget each; answers `{ sent }` | yes |
123126 | `signup` | `{ mode?, dryRun? }`: who may sign up: `open` (default), `invite` (only a person with an open invite link) or `closed` (no new accounts); without `mode` it reads the setting, with `mode` it plans first (`dryRun` is true unless `false`), and applying needs an admin token | yes |
127 | `sizes` | what a child forge's sizes mean: small, medium and large, each with CPU, memory and disk | |
124128 | `spawn` | `{ name, apps?, crew?, dryRun? }`: a child forge, planned first (`dryRun` is true unless `false`); an admin's, and an `ro` token may plan but not make | yes |
125129 | `ssh_keys` | `{ action?, title?, key?, id? }`: list your own SSH keys (default), add one (`key` is an authorized_keys line, `title` optional) or remove one by `id`; the API's rules and errors, add and remove need an `rw` token | yes |
126130 | `stop` | stop one run by its id from `now` | yes |
src/http/mcp/tools/capacity.ts +1
@@ -5,6 +5,7 @@ import { good, bad, type Tool } from "../shared.ts";
55
66 export const tool: Tool = {
77 name: "capacity",
8 doc: "`{ key?, value?, dryRun? }` (forge admin): the forge's capacity and guards, live (crew and checks concurrency, check shards, cell egress, the new-account guard, the sign-in edge, queue depth, child forges; only the first six are settable by `key`); with `key` and `value` (`\"\"` restores the default), planned first (`dryRun` is true unless `false`); applying needs an admin-scope token",
89 description:
910 "The forge's capacity and guards, live. With `key` and `value` (\"\" restores default), plans.",
1011 inputSchema: {
src/http/mcp/tools/limits.ts +1
@@ -5,6 +5,7 @@ import { good, bad, type Tool } from "../shared.ts";
55
66 export const tool: Tool = {
77 name: "limits",
8 doc: "`{ key?, value?, dryRun? }` (forge admin): every limit the forge's owner can hit, with its value, default and bounds; with `key` and `value` (`\"\"` restores the default), planned first (`dryRun` is true unless `false`); a value out of bounds is refused, applying needs an admin-scope token",
89 description:
910 "Every limit the owner can hit, value and bounds. `key`, `value` (\"\" restores) plan.",
1011 inputSchema: {
src/http/mcp/tools/quotas.ts +2 −1
@@ -5,8 +5,9 @@ import { good, bad, type Tool } from "../shared.ts";
55
66 export const tool: Tool = {
77 name: "quotas",
8 doc: "`{ key?, value?, dryRun? }` (forge admin): the per-account quotas `repositories`, `apps`, `storage` (MB), `previews`, `runs`, `checks`, each a number or null for none; enforced when the thing is made or started, never on a forge admin; with `key` and `value` (`\"\"` clears), planned first (`dryRun` is true unless `false`); applying needs an admin-scope token",
outdated

This is wrong in two ways. There are six quotas (repositories, apps, storage, previews, runs, checks; see QUOTA_KEYS in src/settings/quotas.ts), not just repository and app. And each one is enforced (see that file's header comment), so "not enforced yet" is false. Suggested: "{ key?, value?, dryRun? } (forge admin): the per-account quotas repositories, apps, storage (MB), previews, runs, checks, each a number or null for none; enforced when the thing is made or started, never on a forge admin; with key and value (\"\" clears), planned first (dryRun is true unless false); applying needs an admin-scope token"

89 description:
9 "Per-account repo and app quotas (unenforced).",
10 "Per-account quotas. With `key` and `value` (\"\" clears), plans.",
1011 inputSchema: {
1112 type: "object",
1213 properties: {
src/http/mcp/tools/sizes.ts +1
@@ -3,6 +3,7 @@ import { good, type Tool } from "../shared.ts";
33
44 export const tool: Tool = {
55 name: "sizes",
6 doc: "what a child forge's sizes mean: small, medium and large, each with CPU, memory and disk",
67 description:
78 "A child forge's sizes: small, medium and large, each with CPU, memory and disk.",
89 inputSchema: { type: "object", properties: {} },
test/mcp-docs.test.ts −4
@@ -17,7 +17,6 @@ quietLogs();
1717 * The test fails until a documented tool's line is deleted here.
1818 */
1919 const undocumented = new Set<string>([
20 "sizes",
2120 "here",
2221 "asks",
2322 "asks_act",
@@ -28,11 +27,8 @@ const undocumented = new Set<string>([
2827 "model_grant",
2928 "model_ceiling",
3029 "spend",
31 "capacity",
3230 "scorecard",
33 "limits",
3431 "teams",
35 "quotas",
3632 "report",
3733 ]);
3834

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs