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

MCP tools/list drops annotations that only restate the default, and is at least 1,000 bytes smaller #5046

Merged opened this

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

Merged

`tools/list` no longer sends `annotations` for tools that only restated `readOnlyHint: false`. For a forge admin it drops from 36,963 to 34,817 bytes, 2,146 smaller. The 40,000 and 37,000 ceilings are unchanged.

shipped production is serving it deploy 740aa94

opened this

tools/list no longer sends annotations for tools that only restated readOnlyHint: false. For a forge admin it drops from 36,963 to 34,817 bytes, 2,146 smaller. The 40,000 and 37,000 ceilings are unchanged.

I ran bun test test/mcp, which passes. I could not run the type check: bun x tsc --noEmit failed because the bun type definitions are missing, even after bun install. I did not run the full suite or the design lint, since no web files changed.

  • List output: read-only tools still list annotations: { readOnlyHint: true }; write tools list no annotations key. Tools are listed from src/http/mcp.ts, so no tool is renamed, added or removed.
  • report tool: I also removed the readOnlyHint: false annotation from its definition, so it lists none either. No tool sets any other hint, so there was nothing else to keep.
  • New assertion: test/mcp-size.test.ts now checks that no listed tool carries readOnlyHint: false. It also checks that read-only tools say true, by looking for probe and more than five hinted tools.
  • Changed tests: test/mcp.test.ts and test/mcp-upstream.test.ts read annotations.readOnlyHint directly. Those tests were wrong for the new shape, so they now read a missing hint as false, which is MCP's default.

I left the hint on read-only tools alone: it is the only hint any tool sets, and true is not the default.

To try it, call tools/list on /mcp with a token. Write tools have no annotations key, and read-only tools have readOnlyHint: true.

Closes #5031

commented

tools/list no longer sends annotations for tools that only restated readOnlyHint: false. For a forge admin it drops from 36,963 to 34,817 bytes, 2,146 smaller. The 40,000 and 37,000 ceilings are unchanged.

I ran bun test test/mcp, which passes. I could not run the type check: bun x tsc --noEmit failed because the bun type definitions are missing, even after bun install. I did not run the full suite or the design lint, since no web files changed.

  • List output: read-only tools still list annotations: { readOnlyHint: true }; write tools list no annotations key. Tools are listed from src/http/mcp.ts, so no tool is renamed, added or removed.
  • report tool: I also removed the readOnlyHint: false annotation from its definition, so it lists none either. No tool sets any other hint, so there was nothing else to keep.
  • New assertion: test/mcp-size.test.ts now checks that no listed tool carries readOnlyHint: false. It also checks that read-only tools say true, by looking for probe and more than five hinted tools.
  • Changed tests: test/mcp.test.ts and test/mcp-upstream.test.ts read annotations.readOnlyHint directly. Those tests were wrong for the new shape, so they now read a missing hint as false, which is MCP's default.

I left the hint on read-only tools alone: it is the only hint any tool sets, and true is not the default.

To try it, call tools/list on /mcp with a token. Write tools have no annotations key, and read-only tools have readOnlyHint: true.

Approved — before the latest push

Clean, and it does what #5031 asked. tools/list now leaves out annotations when a tool would only say readOnlyHint: false, which is MCP's default. Read-only tools keep readOnlyHint: true. No tool sets any other hint, because the listing builds annotations from t.writes alone. Dropping it from REPORT_TOOL makes the hand-built tool follow the same rule.

Security: nothing changes. No auth, input, or output path is touched; this only changes the response shape.

Tests: at head 5aac1717, bun test test/mcp-size.test.ts test/mcp.test.ts test/mcp-upstream.test.ts gives 45 pass, 0 fail. The new assertion in mcp-size (no tool carries readOnlyHint: false, and more than five tools including probe say true) would fail on main. The edited tests now read a missing hint as false, the way an MCP client does, so the change to them is justified. The 40,000 and 37,000 ceilings are not raised.

Preview: / answers 200. /mcp without a forge token returns the documented unauthorized hint. I have no token for the preview, so I could not see the listed shape there; the tests above cover it.

No page, tty, or README surface is affected: this is an MCP wire-size change only.

commented

I merged main into the branch and pushed it. After the merge, the 124 tests in test/mcp* pass. I didn't run the whole suite, since the forge's check does that on push. The type check couldn't run here because the bun type definitions are missing in this sandbox.

main had already landed the same change: tools/list leaves out readOnlyHint: false, and only read-only tools carry annotations: { readOnlyHint: true }. The four conflicts were all in the wording of comments and assertions, so I took main's version in:

  • src/http/mcp.ts
  • test/mcp-size.test.ts
  • test/mcp-upstream.test.ts
  • test/mcp.test.ts

The one real difference is in test/mcp-size.test.ts. This branch also asserted that at least five tools say readOnlyHint: true and that probe is one of them. With main's version, the size test now only checks that no tool carries readOnlyHint: false.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs