Public: anyone can read this; the crew can change it.
docs/MCP.md describes the capacity and limits tools: `capacity`, `limits`, `quotas`, `sizes` #5302
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/5284-docs-mcp-md-describes-the-capacity-and-l → main 9 commits fork 4 threads · 4 unresolved
docs/MCP.md +4
| @@ -50,6 +50,7 @@ for a tunnel and a forge that sleeps. | ||
| 50 | 50 | | `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 | |
| 51 | 51 | | `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` | | |
| 52 | 52 | | `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 | | |
| 53 | 54 | | `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 | |
| 54 | 55 | | `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 | |
| 55 | 56 | | `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. | ||
| 81 | 82 | | `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 | | |
| 82 | 83 | | `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 | |
| 83 | 84 | | `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 | | |
| 84 | 86 | | `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 | |
| 85 | 87 | | `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 | | |
| 86 | 88 | | `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. | ||
| 104 | 106 | | `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 | |
| 105 | 107 | | `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 | | |
| 106 | 108 | | `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 |
||
| 107 | 110 | | `read_file` | a file (utf-8, or base64 for binary) or a directory listing at a ref, as GET …/contents | | |
| 108 | 111 | | `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` | | |
| 109 | 112 | | `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. | ||
| 121 | 124 | | `sever` | `{ repo }`: cut a spawned forge's link to the forge its code came from; its `forge` repository's owner only; deletes nothing | yes | |
| 122 | 125 | | `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 | |
| 123 | 126 | | `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 | | | |
| 124 | 128 | | `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 | |
| 125 | 129 | | `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 | |
| 126 | 130 | | `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"; | ||
| 5 | 5 | |
| 6 | 6 | export const tool: Tool = { |
| 7 | 7 | 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", | |
| 8 | 9 | description: |
| 9 | 10 | "The forge's capacity and guards, live. With `key` and `value` (\"\" restores default), plans.", |
| 10 | 11 | inputSchema: { |
src/http/mcp/tools/limits.ts +1
| @@ -5,6 +5,7 @@ import { good, bad, type Tool } from "../shared.ts"; | ||
| 5 | 5 | |
| 6 | 6 | export const tool: Tool = { |
| 7 | 7 | 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", | |
| 8 | 9 | description: |
| 9 | 10 | "Every limit the owner can hit, value and bounds. `key`, `value` (\"\" restores) plan.", |
| 10 | 11 | inputSchema: { |
src/http/mcp/tools/quotas.ts +2 −1
| @@ -5,8 +5,9 @@ import { good, bad, type Tool } from "../shared.ts"; | ||
| 5 | 5 | |
| 6 | 6 | export const tool: Tool = { |
| 7 | 7 | 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 ( |
||
| 8 | 9 | description: |
| 9 | "Per-account repo and app quotas (unenforced).", | |
| 10 | "Per-account quotas. With `key` and `value` (\"\" clears), plans.", | |
| 10 | 11 | inputSchema: { |
| 11 | 12 | type: "object", |
| 12 | 13 | properties: { |
src/http/mcp/tools/sizes.ts +1
| @@ -3,6 +3,7 @@ import { good, type Tool } from "../shared.ts"; | ||
| 3 | 3 | |
| 4 | 4 | export const tool: Tool = { |
| 5 | 5 | name: "sizes", |
| 6 | doc: "what a child forge's sizes mean: small, medium and large, each with CPU, memory and disk", | |
| 6 | 7 | description: |
| 7 | 8 | "A child forge's sizes: small, medium and large, each with CPU, memory and disk.", |
| 8 | 9 | inputSchema: { type: "object", properties: {} }, |
test/mcp-docs.test.ts −4
| @@ -17,7 +17,6 @@ quietLogs(); | ||
| 17 | 17 | * The test fails until a documented tool's line is deleted here. |
| 18 | 18 | */ |
| 19 | 19 | const undocumented = new Set<string>([ |
| 20 | "sizes", | |
| 21 | 20 | "here", |
| 22 | 21 | "asks", |
| 23 | 22 | "asks_act", |
| @@ -28,11 +27,8 @@ const undocumented = new Set<string>([ | ||
| 28 | 27 | "model_grant", |
| 29 | 28 | "model_ceiling", |
| 30 | 29 | "spend", |
| 31 | "capacity", | |
| 32 | 30 | "scorecard", |
| 33 | "limits", | |
| 34 | 31 | "teams", |
| 35 | "quotas", | |
| 36 | 32 | "report", |
| 37 | 33 | ]); |
| 38 | 34 |
Nit, not blocking: the bare listing shows all eight settings, but the MCP
keyenum only accepts six (queue.depthandchildren.maxare 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.