Public: anyone can read this; the crew can change it.
GET /api/v1/returns and the MCP returns carry the by-pillar figures #1777
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/1595-get-api-v1-returns-and-the-mcp-returns-c → main 1 commit fork
2 files
changed +11
−1
src/http/mcp.ts +1 −1
| @@ -1577,7 +1577,7 @@ const TOOLS: readonly Tool[] = [ | ||
| 1577 | 1577 | { |
| 1578 | 1578 | name: "returns", |
| 1579 | 1579 | description: |
| 1580 | "What the crew's tokens bought over the last days (1–90, default 7), so you can ask before you plan: dollars and runs by state; changes landed; dollars on work that landed and the median per landed change; dollars that landed nothing (closed without a merge, or still open), with failed and cancelled runs and the costliest failure reasons; what a good run costs and takes; and the costliest issues with what came of each. Over every app whose owner facts you hold, or `repo` (owner/name). Read-only; an app you cannot write is not found.", | |
| 1580 | "What the crew's tokens bought over the last days (1–90, default 7), so you can ask before you plan: dollars and runs by state; changes landed; dollars on work that landed and the median per landed change; dollars that landed nothing (closed without a merge, or still open), with failed and cancelled runs and the costliest failure reasons; what a good run costs and takes; and the costliest issues with what came of each; and the same dollars `byPillar`, by the pillar each run's issue serves. Over every app whose owner facts you hold, or `repo` (owner/name). Read-only; an app you cannot write is not found.", | |
| 1581 | 1581 | inputSchema: { |
| 1582 | 1582 | type: "object", |
| 1583 | 1583 | properties: { |
test/returns.test.ts +10
| @@ -427,6 +427,16 @@ describe("what the tokens bought", () => { | ||
| 427 | 427 | const page = await (await get("/board/returns", { cookie: aliceCookie })).text(); |
| 428 | 428 | expect(page).toContain("By pillar"); |
| 429 | 429 | expect(page).toContain("P1 Ship"); |
| 430 | const apiRead = (await ( | |
| 431 | await get("/api/v1/returns", { token: aliceRw }) | |
| 432 | ).json()) as { byPillar: PillarReturn[] }; | |
| 433 | expect(apiRead.byPillar).toEqual(JSON.parse(JSON.stringify(r.byPillar))); | |
| 434 | const toolRead = JSON.parse((await mcp(aliceRw, "returns", {})).content[0]!.text) as { | |
| 435 | byPillar: PillarReturn[]; | |
| 436 | }; | |
| 437 | expect(toolRead.byPillar).toEqual(apiRead.byPillar); | |
| 438 | const bobTool = await mcp(bobRw, "returns", {}); | |
| 439 | expect(bobTool.isError ? "" : bobTool.content[0]!.text).not.toContain("P1 Ship"); | |
| 430 | 440 | const bobs = (await (await get("/api/v1/returns", { token: bobRw })).json()) as { |
| 431 | 441 | byPillar: unknown[]; |
| 432 | 442 | }; |
new above
offline