Skip to content

2026.09.9

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 06 Sep 20:05
· 30 commits to main since this release

Breaking

  • Make discovery a tool, and generate the surface from one catalogue (06945d2d)

    The MCP tool listing is sent to a model on every conversation that touches
    Studio, before it has asked for anything. It is now 1696 tokens across 13 tools,
    down from 2115 across 14 — a fifth off every session — and it gained a discovery
    tool while shrinking.

    studio_help is the new route to the detail the schemas leave out. Call it with
    no topic for an index of every tool, or with a tool name for that tool's accepted
    values, JSON body shapes and semantics.

    ADR-0050 had put that detail in the studio://tools resource, on the reasoning
    that a host fetches a resource once and keeps it. That is true of hosts that read
    resources. resources is an optional server capability and nothing in the MCP
    specification obliges a client to call resources/read — ever. On a host that
    skips them, ADR-0050 did not make discovery progressive; it made it absent, and a
    model was left inferring valid values by triggering rejections. Tools are the one
    part of MCP every host implements, so the detail moved behind one. studio://tools
    remains as a generated mirror that nothing depends on.

    Because that channel is now reliable, every other schema dropped the hedging text
    it carried in case the resource was never read — spelled defaults, type codes,
    "see studio://tools" pointers. The help tool costs about thirty-five tokens and
    licensed stripping several hundred, which is why the listing is smaller despite
    being one tool larger.

    Rejections now name studio_help alongside the values they would have accepted,
    so a wrong guess is a recovery rather than a retry loop.

    The server instructions block is generated from the same catalogue instead of
    being retyped in application.yml. The hand-written one had already drifted: it
    omitted queue_lifecycle and message_body and never named a discovery route.
    Under a host that searches tools rather than sending the whole listing, that text
    is the only thing guaranteed to be read, so a stale copy did not merely go out of
    date — it told a model that two capabilities the product has did not exist. The
    build now fails when a registered tool is missing from the catalogue.

    Two further checks are enforced: no tool may declare itself both read-only and
    destructive, and a tool's declared posture must match the catalogue's. A host
    gates a whole tool on one destructiveHint, so a read reachable through a tool
    that can purge would make every read prompt the operator — which is how an
    operator is trained to reflex-approve the purge.

    The budget ceilings ratchet down with the win rather than banking it as headroom:
    per-tool 200 → 175, average 160 → 135, calibrated against a measured run.

Added

  • Make discovery a tool, and generate the surface from one catalogue (06945d2d)

    The MCP tool listing is sent to a model on every conversation that touches
    Studio, before it has asked for anything. It is now 1696 tokens across 13 tools,
    down from 2115 across 14 — a fifth off every session — and it gained a discovery
    tool while shrinking.

    studio_help is the new route to the detail the schemas leave out. Call it with
    no topic for an index of every tool, or with a tool name for that tool's accepted
    values, JSON body shapes and semantics.

    ADR-0050 had put that detail in the studio://tools resource, on the reasoning
    that a host fetches a resource once and keeps it. That is true of hosts that read
    resources. resources is an optional server capability and nothing in the MCP
    specification obliges a client to call resources/read — ever. On a host that
    skips them, ADR-0050 did not make discovery progressive; it made it absent, and a
    model was left inferring valid values by triggering rejections. Tools are the one
    part of MCP every host implements, so the detail moved behind one. studio://tools
    remains as a generated mirror that nothing depends on.

    Because that channel is now reliable, every other schema dropped the hedging text
    it carried in case the resource was never read — spelled defaults, type codes,
    "see studio://tools" pointers. The help tool costs about thirty-five tokens and
    licensed stripping several hundred, which is why the listing is smaller despite
    being one tool larger.

    Rejections now name studio_help alongside the values they would have accepted,
    so a wrong guess is a recovery rather than a retry loop.

    The server instructions block is generated from the same catalogue instead of
    being retyped in application.yml. The hand-written one had already drifted: it
    omitted queue_lifecycle and message_body and never named a discovery route.
    Under a host that searches tools rather than sending the whole listing, that text
    is the only thing guaranteed to be read, so a stale copy did not merely go out of
    date — it told a model that two capabilities the product has did not exist. The
    build now fails when a registered tool is missing from the catalogue.

    Two further checks are enforced: no tool may declare itself both read-only and
    destructive, and a tool's declared posture must match the catalogue's. A host
    gates a whole tool on one destructiveHint, so a read reachable through a tool
    that can purge would make every read prompt the operator — which is how an
    operator is trained to reflex-approve the purge.

    The budget ceilings ratchet down with the win rather than banking it as headroom:
    per-tool 200 → 175, average 160 → 135, calibrated against a measured run.